Question

Existe-t-il un moyen d’obtenir le préprocesseur C / C ++ ou un modèle ou de modifier ou hacher les fichiers __FILE__ et __LINE__ et peut-être une autre entrée externe, telle qu'un numéro de construction, en un seul numéro court pouvant être cité dans les journaux ou messages d'erreur?

(L'intention serait de pouvoir inverser (une liste de candidats en cas de perte) si nécessaire lorsqu'un client le mentionne dans un rapport de bogue.)

Était-ce utile?

La solution

Vous devrez utiliser une fonction pour effectuer le hachage et créer un code à partir de __ LINE __ et de __ FILE __ , car le préprocesseur C ne peut pas effectuer de tâches aussi complexes.

Quoi qu’il en soit, vous pouvez vous inspirer de cet article pour savoir si solution différente peut être mieux adaptée à votre situation.

Autres conseils

Eh bien ... vous pourriez utiliser quelque chose comme:

((*(int*)__FILE__ && 0xFFFF0000) | version << 8 | __LINE__ )

Ce ne serait pas parfaitement unique, mais cela pourrait fonctionner pour ce que vous voulez. Pourrait changer ces OU en +, ce qui pourrait fonctionner mieux pour certaines choses.

Naturellement, si vous pouvez réellement créer un hashcode, vous voudrez probablement le faire.

J'avais besoin de série valuse dans un de mes projets et je les ai obtenus en créant un modèle spécialisé sur __ LINE __ et __ FILE __ , ce qui a abouti à un fichier int compile time output to stdout) une spécialisation de modèle pour ses entrées ayant pour résultat le numéro de ligne de ce modèle. Celles-ci ont été collectées la première fois via le compilateur, puis transférées dans un fichier de code et le programme a été compilé à nouveau. Chaque fois que chaque emplacement où le modèle a été utilisé a reçu un numéro différent.

(fait en D donc cela pourrait ne pas être possible en 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;
}

Une solution plus simple consisterait à conserver un "emplacement d'erreur" global statique. variable.

#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 sans le printf .. Incrémentez simplement le errloc chaque fois que vous croisez un point de trace. Ensuite, vous pouvez corréler la valeur à la ligne / nombre / version générée par vos versions de débogage assez facilement.

Vous devez inclure la version ou le numéro de version, car ces emplacements d'erreur peuvent changer avec n'importe quelle version.

Ne fonctionne pas bien si vous ne pouvez pas reproduire les chemins de code.

__ FILE__ est un pointeur sur le segment des constantes de votre programme. Si vous affichez la différence entre cette constante et une autre constante, vous obtiendrez un résultat indépendant de toute relocalisation, etc.:

extern const char g_DebugAnchor;
#define FILE_STR_OFFSET (__FILE__ - &g_DebugAnchor)

Vous pouvez ensuite le signaler ou le combiner d'une manière ou d'une autre avec le numéro de ligne, etc. Les bits du milieu de FILE_STR_OFFSET sont probablement les plus intéressants.

Eh bien, si vous affichez vous-même le message à l'utilisateur (au lieu d'afficher une adresse ou une fonction d'accident du système), rien ne vous empêche d'afficher exactement ce que vous voulez.

Par exemple:

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;
}

Vous utiliseriez cela comme

buildErrorCodes(__FILE__, __LINE__, BUILD_CODE) 

et le sortir en hexadécimal. Il ne serait pas très difficile de décoder ...

(Modifié - les commentateurs sont corrects, je devais être fou pour spécifier 5 bits pour le numéro de ligne. Modulo 4096, cependant, les lignes avec des messages d'erreur ne risquent pas d'entrer en collision. 5 bits pour la construction est encore correct - modulo 32 signifie que seules 32 constructions peuvent être en attente ET que l'erreur se produit toujours sur la même ligne.)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top