Registrar cada archivo fuente C / C ++ para crear una lista de tiempo de ejecución de las fuentes usadas

StackOverflow https://stackoverflow.com/questions/618581

Pregunta

Para una biblioteca de depuración y registro, quiero poder encontrar, en tiempo de ejecución, una lista de todos los archivos fuente que el proyecto ha compilado y vinculado. Supongo que incluiré algún tipo de encabezado en cada archivo fuente, y la macro __FILE__ del preprocesador puede darme una constante de caracteres para ese archivo, por lo que solo necesito de alguna manera & Quot; broadcast & Quot; esa información de cada archivo que debe reunir una función de tiempo de ejecución.

La pregunta es cómo hacer esto con elegancia, y especialmente si se puede hacer desde C en lugar de C ++. En C ++ probablemente trataría de hacer una clase con un almacenamiento estático para contener la lista de nombres de archivo. Cada archivo de encabezado crearía una instancia estática local de archivo de esa clase, que en la creación agregaría el puntero FILE o lo que sea a los miembros de datos estáticos de la clase, tal vez como una lista vinculada.

Pero no creo que esto funcione en C, e incluso en C ++ no estoy seguro de que esté garantizado que se creará cada elemento.

¿Fue útil?

Solución

No haría ese tipo de cosas en el código. Escribiría una herramienta que analizara el archivo del proyecto (vcproj, makefile o incluso simplemente escaneara el directorio del proyecto en busca de archivos * .c *) y generara un archivo fuente C adicional que contenía los nombres de todos los archivos fuente en algún tipo de estructura de datos inicializada.

Luego, convertiría esa herramienta en parte del proceso de compilación para que cada vez que realice una compilación, todo esto suceda automáticamente. En tiempo de ejecución, todo lo que tendría que hacer es leer la estructura de datos que se creó.

Otros consejos

Estoy de acuerdo con Ferruccio, la mejor manera de hacerlo es en el sistema de compilación, no en el código en sí. Como una expansión de su idea, agregue un destino a su sistema de compilación que descargue una lista de los archivos (que debe saber de todos modos) a un archivo C como una cadena o matriz de cadenas, y compile este archivo en su fuente. Esto evita muchas complicaciones en la fuente y es expandible si desea agregar información adicional, como el número de versión de su sistema de control de código fuente, quién creó el ejecutable, etc.

Hay una forma estándar en UNIX y Linux: ident. Para cada archivo fuente que crea una etiqueta de identificación, generalmente es asignada por su sistema de control de versiones, p. palabras clave SVN .

Luego, para averiguar el nombre y la revisión de cada archivo fuente, simplemente use el comando <=>. Si necesita hacerlo en tiempo de ejecución, consulte cómo <=> lo hace: la fuente debe estar disponible gratuitamente.

No hay forma de hacerlo en C. En C ++ puedes crear una clase como esta:

struct Reg {
   Reg( const char * file ) {
      StaticDictionary::Register( file );
};

donde StaticDictionary es un contenedor singleton para todos sus nombres de archivo. Luego, en cada archivo fuente:

static Reg regthisfile( __FILE__ );

Desearía convertir el diccionario en Meyers singleton para evitar problemas de orden de creación.

No creo que pueda hacer esto en la forma en que se describe en un " pasivo " modo. Es decir, va a ejecutar de alguna manera el código para cada archivo fuente que se agregará al registro, es difícil hacer que suceda automáticamente.

Por supuesto, es posible que pueda hacer que ese código sea muy discreto usando macros. Puede ser problemático para los archivos fuente C que no tienen un & Quot; punto de entrada & Quot ;, así que si su código no está organizado como & Quot; módulos & Quot ;, con p. Ej. una función init() para cada módulo, puede ser difícil. El código de inicialización estática podría ser posible, no estoy 100% seguro si el orden en que se inicializan las cosas crea problemas aquí.

Usar static almacenamiento en el módulo de registro suena como una idea excelente, una lista enlazada simple o una tabla hash simple debería ser lo suficientemente fácil de implementar, si su proyecto no incluye ninguna biblioteca de utilidad de uso general.

En C ++ su solución funcionará. Está garantizado.

Editar: acabo de encontrar una solución en mi cabeza: cambiar una regla en su archivo MAKE para agregar '-incluye " cfiles_register.h "' a cada 'g ++ file.cpp'.

%.o : %.cpp
    $(CC) -include 'cfiles_register.h' -o $@ $<

ponga su propuesta en la implementación de la pregunta a ese 'cfiles_register.h'.

Usar instancias estáticas en C ++ funcionaría bien.

También puede hacer esto en C, pero necesita usar funciones específicas de tiempo de ejecución: para MSVC CRT, eche un vistazo a http://www.codeguru.com/cpp/misc/misc/threadsprocesses/article.php/c6945/

Para C - podría hacerlo con una macro - defina una variable llamada correspondiente a su archivo, y luego podría escanear los símbolos de su ejecutable, solo como una idea:

 #define TRACK_FILE(name) char _file_tracker_##name;

úsala en tu my_c_file.c así:

 TRACK_FILE(my_c_file_c)

y luego grep todos los nombres de archivo / variable del binario como este

nm my-binary | grep _file_tracker

No es realmente agradable, pero ...

Idea horrible, estoy seguro, pero usa un singleton. Y en cada archivo haga algo como

  Singleton.register(__FILE__); 

a alcance global. Sin embargo, solo funcionará en archivos cpp. Hice algo como esto hace años como novato, y funcionó. Pero me daría miedo hacerlo ahora. Agregaría un paso de compilación ahora.

Estoy de acuerdo con aquellos que dicen que es mejor evitar hacer esto en tiempo de ejecución, pero en C, puede inicializar una variable estática con una llamada a la función, es decir, en cada archivo:

static int doesntmatter = register( __FILE__);
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top