2011-07-17 20 views
8

Digamos que hay tres encabezados AAA.h, BBB.h y MyLib.h. MyLib.h necesita incluir AAA.h y BBB.h para funcionar correctamente.¿Hay alguna forma de detectar cuándo se satisfacen "accidentalmente" las dependencias de archivos?

Ahora, simplemente sucede que BBB.h incluye también AAA.h en ella, pero esto es estrictamente debido a la implementación, un detalle que MyLib.h no deberían tener que preocuparse.

Sin embargo, por error, el autor de MyLib.h omite incluir AAA.h y nunca lo nota. Normalmente, esto no da como resultado un error o advertencia, hasta donde yo sé. Más tarde, alguien cambia los detalles de implementación de BBB.h para que AAA.h ya no sea necesario y, por lo tanto, se elimine. Ahora MyLib no compila porque las partes internas de la biblioteca BBB han cambiado.

¿Hay alguna manera de error o advertencia en casos como estos? Sospecho (si esto es posible) que se necesitaría algún tipo de anotación en el encabezado.

+1

Tiene razón, requeriría una anotación, ya que a veces los encabezados * están documentados * para incluir otros encabezados, o los encabezados se implementan internamente al incluir otros archivos. No querrá pasar por una gran cantidad de falsos positivos porque su código se basa en algo definido en '/ compiler/internals/stl_vector_impl.h', cuando toda su aplicación incluida era' ', o donde las bibliotecas definidas por el usuario han seguido una organización similar. –

+1

GCC tiene una opción para ver qué encabezados incluyen cualesquiera otros: http://stackoverflow.com/questions/5258826/how-to-see-the-actual-order-of-include-files-after-preprocessing/5258938# 5258938 –

Respuesta

2

Creo que es mejor evitar depender de otros encabezados en los encabezados de la interfaz pública, por lo que este problema no aparece.

Los encabezados de la interfaz pública no deben contener definiciones innecesarias.

Existen varios trucos para hacer cosas sin incluir archivos. Por ejemplo, puede declarar struct tags manualmente si solo necesita un puntero (las bibliotecas que solo definen un typedef lo frustran) y puede usar _Bool en lugar de bool para evitar <stdbool.h>. Desafortunadamente, muchos tipos importantes, como size_t y uint32_t, solo se definen en los encabezados.

Algunos paquetes llegan a definir su propio foo_uint32_t usando configure para que no necesiten incluir <stdint.h> en sus encabezados de interfaz pública. Esto es bastante complicado ya que los tipos deben ser exactamente iguales para evitar confusiones: incluso si sizeof(unsigned int) == sizeof(unsigned long) == 4 son de tipos diferentes. Por lo tanto, puede no valer la pena.

2

Usted está ilustrando por qué incluir encabezados apesta como un método para importar espacios de nombres.

La única solución que veo es la disciplina. Las funciones de la biblioteca estándar requieren que incluya el encabezado apropiado, sus proyectos deben adoptar el mismo estándar. Los encabezados como MyLib.h deben contener solo los tipos que define y sus prototipos de función. Si necesita usar un cierto tipo para hacer su trabajo, el encabezado debe incluirse explícitamente, por lo que si necesita una definición de AAA debe incluir AAA.h y si necesita alguna definición de BBB, debe incluir BBB.h, así como cualquier archivo de implementación (digamos MyLib.c) debe incluir explícitamente todos los encabezados para cualquier definición que use, independientemente de estar seguro de que MyLib.h los incluye también. Nunca suponga que un encabezado define algo implícitamente incluyendo otros encabezados.

Esto se puede verificar fácilmente usando un IDE, que generalmente le indicará dónde se define un nombre y, por lo tanto, puede averiguar fácilmente qué archivo de inclusión usar. Puede haber herramientas disponibles que hagan este tipo de comprobación.

Cuestiones relacionadas