Registrar arquivo de origem de cada C / C ++ para criar uma lista de execução das fontes utilizadas

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

Pergunta

Para uma biblioteca de depuração e exploração madeireira, eu quero ser capaz de encontrar, em tempo de execução, uma lista de todos os arquivos de origem que o projeto compilado e ligado. Eu suponho eu estarei incluindo algum tipo de cabeçalho em cada arquivo de origem e o pré-processador __FILE__ macro pode me dar uma constante de caracteres para esse arquivo, então eu só preciso de algum modo "broadcast" que informações de cada arquivo a ser recolhida por um runtime função.

A questão é como elegantemente fazer isso, e especialmente se ele pode ser feito a partir C ao contrário de C ++. Em C ++ eu provavelmente tentar fazer uma classe com uma armazenagem estática para armazenar a lista de nomes de arquivos. Cada arquivo de cabeçalho criaria uma instância estática arquivo-local dessa classe, que na criação vai anexar o ponteiro do arquivo ou o que quer em membros de dados estáticos da classe, talvez como uma lista ligada.

Mas eu não acho que isso vai funcionar em C, e até mesmo em C ++ Eu não tenho certeza é garantido que cada elemento será criado.

Foi útil?

Solução

Eu não faria esse tipo de coisa certa no código. Eu ia escrever uma ferramenta que analisado o arquivo de projeto (vcproj, makefile ou mesmo apenas digitalizar o diretório do projeto para * .c * arquivos) e gerado um arquivo adicional fonte C que continha os nomes de todos os arquivos de origem em algum tipo de pré- estrutura de dados inicializado.

Eu, então, fazer essa parte da ferramenta do processo de construção de modo que cada vez que você faz uma compilação isso tudo acontece automaticamente. Em tempo de execução, tudo que você tem a fazer é ler que estrutura de dados que foi construído.

Outras dicas

Eu concordo com Ferruccio, a melhor maneira de fazer isso é no sistema de compilação, não o próprio código. Como uma expansão da sua ideia, adicione um alvo para o seu sistema de construção que despeja uma lista dos arquivos (que tem de saber de qualquer maneira) para um arquivo C como uma string, ou matriz de strings, e compilar esse arquivo para sua fonte. Isso evita um monte de complicação na fonte, e é expansível, se você quiser adicionar informações adicionais, como o número da versão do seu sistema de controle de código fonte, que construiu o executável, etc.

Há uma maneira padrão no UNIX e Linux - ident. Para cada arquivo de origem que você crie tag ID - geralmente é atribuído pelo seu sistema de controle de versão, por exemplo, SVN palavras-chave .

Depois de descobrir o nome e revisão de cada arquivo de origem que você acabou de usar o comando ident. Se você precisa fazê-lo em tempo de execução verificar a forma como ident faz isso -. Fonte para ele deve ser livremente disponível

Não há nenhuma maneira de fazê-lo em C. Em C ++ você pode criar uma classe como este:

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

onde StaticDictionary é um recipiente singleton para todos os seus nomes de arquivo. Então, em cada arquivo de origem:

static Reg regthisfile( __FILE__ );

Você gostaria de fazer o dicionário a Meyers singleton a fim evitar problemas de criação.

Eu não acho que você pode fazer isso da maneira que você delinear em um modo "passivo". Ou seja, você está indo para o código de alguma forma executar para cada arquivo de origem para ser adicionado ao registro, é difícil conseguir que isso aconteça automaticamente.

É claro, é possível que você pode fazer esse código muito discreto usando macros. Pode ser problemático para arquivos de origem C que não têm um "ponto de entrada", por isso, se o seu código não estiver organizado como "módulos", com por exemplo, uma função init() para cada módulo, pode ser difícil. código de inicialização estática pode ser possível, eu não estou 100% de certeza se a ordem em que as coisas são inicializados cria problemas aqui.

Usando armazenamento static nos sons do módulo de registro como uma excelente ideia, uma lista ligada simples ou tabela hash simples deve ser bastante fácil de implementar, se seu projeto já não incluir qualquer biblioteca de utilitário de propósito geral.

Em C ++ sua solução vai funcionar. É garantido.

Editar: Só descobri uma solução na minha cabeça: Alterar uma regra no seu makefile para adicionar 'Cfiles_register.h "-include' para cada 'g ++ file.cpp'.

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

colocar a sua proposta na questão implemnatation para que 'cfiles_register.h'.

Usando exemplos estáticos em C ++ iria funcionar bem.

Você pode fazer isso também em C, mas você precisa usar específico de tempo de execução apresenta - para MSVC CRT dar uma olhada em http://www.codeguru.com/cpp/misc/misc/threadsprocesses/article.php/c6945/

Para C - você poderia fazê-lo com um macro - definir uma variável chamada correspondente ao seu arquivo, e então você pode digitalizar os símbolos de seu executável, assim como uma idéia:

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

usá-lo em sua my_c_file.c assim:

 TRACK_FILE(my_c_file_c)

e que o grep todos os arquivos / nomes de variáveis ??do binário como este

nm my-binary | grep _file_tracker

Não é realmente bom, mas ...

idéia horrível, eu tenho certeza, mas usar um singleton. E em cada arquivo fazer algo como

  Singleton.register(__FILE__); 

no escopo global. Só vai trabalhar em arquivos CPP embora. Eu fiz algo parecido com isso anos atrás, como um novato, e funcionou. Mas eu tremo para fazê-lo agora. Eu gostaria de acrescentar uma etapa de compilação agora.

Eu concordo com aqueles que dizem que é melhor evitar fazer isso em tempo de execução, mas em C, você pode inicializar uma variável estática com uma chamada de função, isto é, em cada arquivo:

static int doesntmatter = register( __FILE__);
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top