Domanda

Esiste un modo per ottenere il preprocessore C / C ++ o un modello o simile per manipolare / hash __FILE__ e __LINE__ e forse qualche altro input esterno come un numero di build in un singolo numero breve che può essere citato nei registri o messaggi di errore?

(L'intenzione sarebbe quella di essere in grado di invertire (in un elenco di candidati se è in perdita) quando necessario quando un cliente lo cita in una segnalazione di bug.)

È stato utile?

Soluzione

Dovrai utilizzare una funzione per eseguire l'hash e creare un codice da __LINE__ e __FILE__ poiché il preprocessore C non è in grado di svolgere compiti così complessi.

Ad ogni modo, puoi prendere ispirazione da questo articolo per vedere se un soluzioni diverse possono essere più adatte alla tua situazione.

Altri suggerimenti

Beh ... potresti usare qualcosa del tipo:

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

Non sarebbe perfettamente unico, ma potrebbe funzionare per quello che vuoi. Potrebbe cambiare questi OR in +, che potrebbe funzionare meglio per alcune cose.

Naturalmente, se puoi effettivamente creare un hashcode, probabilmente vorrai farlo.

Avevo bisogno di un serial valuse in un mio progetto e li ho ottenuti creando un modello specializzato in __LINE__ e __FILE__ e ho generato un int oltre a generare (come compilare il tempo di output su stdout) una specializzazione di modello per i suoi input che ha portato al numero di riga di quel modello. Questi sono stati raccolti la prima volta attraverso il compilatore e quindi scaricati in un file di codice e il programma è stato nuovamente compilato. Quella volta ogni posizione in cui è stato utilizzato il modello ha ottenuto un numero diverso.

(fatto in D quindi potrebbe non essere possibile in 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;
}

Una soluzione più semplice sarebbe quella di mantenere una posizione di errore "statica" globale " variabile.

#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

O senza printf .. Basta incrementare errloc ogni volta che si attraversa un punto di traccia. Quindi puoi correlare il valore alla riga / numero / versione sputata dai build di debug abbastanza facilmente.

Dovresti includere la versione o il numero di build, poiché tali posizioni degli errori potrebbero cambiare con qualsiasi build.

Non funziona bene se non riesci a riprodurre i percorsi del codice.

__FILE__ è un puntatore nel segmento delle costanti del programma. Se si genera la differenza tra quella e qualche altra costante, si dovrebbe ottenere un risultato indipendente da qualsiasi trasferimento, ecc .:

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

Puoi quindi segnalarlo o combinarlo in qualche modo con il numero di riga, ecc. I bit centrali di FILE_STR_OFFSET sono probabilmente i più interessanti.

Bene, se stai mostrando tu stesso il messaggio all'utente (invece che avere un indirizzo o funzione di crash essere visualizzato dal sistema), non c'è nulla che ti impedisca di visualizzare esattamente quello che vuoi.

Ad esempio:

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

Lo useresti come

buildErrorCodes(__FILE__, __LINE__, BUILD_CODE) 

e output in esadecimale. Non sarebbe molto difficile decodificare ...

(Modificato: i commentatori sono corretti, devo essere stato pazzo per specificare 5 bit per il numero di riga. Modulo 4096, tuttavia, è probabile che le righe con messaggi di errore non si scontrino. 5 bit per la compilazione sono ancora validi - modulo 32 significa che solo 32 build possono essere in sospeso E far sì che l'errore si verifichi ancora sulla stessa riga.)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top