Desconfiguração __FILE__ e __LINE__ em código para citar?
-
02-07-2019 - |
Pergunta
Existe uma maneira de obter o C / C ++ pré-processador ou um modelo ou como a mangle / hash __FILE__ e __LINE__ e talvez alguma outra entrada externa como uma build-número em um único número curto que pode ser citado em registros ou mensagens de erro?
(A intenção seria a de ser capaz de revertê-la (para uma lista de candidatos, se a sua lossy), quando necessário quando um cliente cita em um relatório de bug.)
Solução
Você terá que usar uma função para executar a hashing e criar um código de __LINE__
e __FILE__
como o pré-processador C não é capaz de fazer tais tarefas complexas.
De qualquer forma, você pode tirar inspiração por este artigo para ver se um solução diferente pode ser mais adequado à sua situação.
Outras dicas
Bem ... você poderia usar algo como:
((*(int*)__FILE__ && 0xFFFF0000) | version << 8 | __LINE__ )
Não seria perfeitamente original, mas ele pode trabalhar para o que você quer. Poderia mudar essas RUP para +, que pode funcionar melhor para algumas coisas.
Naturalmente, se você pode realmente criar um código hash, você provavelmente vai querer fazer isso.
Eu precisava valuse série em um projeto meu e tenho-os, fazendo um modelo que se especializou em __LINE__
e __FILE__
e resultou em um int, bem como de geração (como saída tempo de compilação para stdout) uma especialização de modelo para ele é entradas que resultaram no número de linha de base nesse modelo. Estes foram coletados pela primeira vez através do compilador e, em seguida, despejado em um arquivo de código e o programa foi compilado novamente. Esse tempo cada local que o modelo foi utilizado tem um número diferente.
(feito em D, de modo que pode não ser possível em C ++)
template Serial(char[] file, int line)
{
prgams(msg,
"template Serial(char[] file : \"~file~"\", int line : "~line.stringof~")"
"{const int Serial = __LINE__;");
const int Serial = -1;
}
A solução mais simples seria a de manter um estático "localização de erro" variável global.
#ifdef DEBUG
#define trace_here(version) printf("[%d]%s:%d {%d}\n", version, __FILE__, __LINE__, errloc++);
#else
#define trace_here(version) printf("{%lu}\n", version<<16|errloc++);
#endif
Ou sem a printf .. Basta incrementar a toda errloc você cruza uma tracepoint. Então você pode correlacionar o valor para a linha / número / versão cuspir pelo seu compilações de depuração muito facilmente.
Você precisaria incluir versão ou número de compilação, porque esses locais de erro poderia mudar a qualquer construção.
não funciona bem se você não pode reproduzir os caminhos de código.
__ FILE__ é um ponteiro para o segmento constantes do seu programa. Se você saída a diferença entre isso e alguma outra constante que você deve obter um resultado que é independente de qualquer deslocalização, etc:
extern const char g_DebugAnchor;
#define FILE_STR_OFFSET (__FILE__ - &g_DebugAnchor)
Você pode, então, relatam que, ou combiná-lo de alguma forma com o número da linha, etc. Os bits do meio de FILE_STR_OFFSET são provavelmente o mais interessante.
Bem, se você está exibindo a mensagem para o usuário se (em oposição a ter um endereço ou função acidente ser exibido pelo sistema), não há nada para mantê-lo de exibir exatamente o que você quer.
Por exemplo:
typedef union ErrorCode {
struct {
unsigned int file: 15;
unsigned int line: 12; /* Better than 5 bits, still not great
Thanks commenters!! */
unsigned int build: 5;
} bits;
unsigned int code;
} ErrorCode;
unsigned int buildErrorCodes(const char *file, int line, int build)
{
ErrorCode code;
code.bits.line=line & ((1<<12) - 1);
code.bits.build=build & ((1<< 5) - 1);
code.bits.file=some_hash_function(file) & ((1<<15) - 1);
return code.code;
}
Você usaria isso como
buildErrorCodes(__FILE__, __LINE__, BUILD_CODE)
e sua saída será em hexadecimal. Não seria muito difícil para decodificar ...
(Editado - os comentaristas estão corretos, I deve ter sido nozes para especificar 5 bits para o número da linha Modulo 4096, no entanto, linhas com mensagens de erro não são susceptíveis de colidir 5 bits para construção ainda está bem.. - módulo 32 significa que apenas 32 constrói pode ser excelente e tem o erro ainda acontecem na mesma linha.)