Pregunta

¿Hay alguna manera de obtener el preprocesador de C / C ++ o una plantilla o similar para modificar / hash el __FILE__ y __LINE__ y quizás alguna otra entrada externa como un número de compilación en un solo número corto que se pueda citar en registros o mensajes de error?

(La intención sería poder revertirlo (a una lista de candidatos si tiene pérdidas) cuando sea necesario cuando un cliente lo cita en un informe de error).

¿Fue útil?

Solución

Tendrá que usar una función para realizar el hashing y crear un código desde __LINE__ y __FILE__ ya que el preprocesador de C no puede realizar tales tareas complejas.

De todos modos, puedes inspirarte en este article para ver si Una solución diferente puede adaptarse mejor a su situación.

Otros consejos

Bueno ... podrías usar algo como:

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

No sería perfectamente único, pero podría funcionar para lo que quieras. Podría cambiar esos OR a +, lo que podría funcionar mejor para algunas cosas.

Naturalmente, si realmente puedes crear un código hash, probablemente querrás hacer eso.

Necesité valuse en serie en un proyecto mío y los obtuve al hacer una plantilla que se especializó en __LINE__ y __FILE__ y dio como resultado un int y una generación (como compilar la salida de tiempo a la salida estándar) una especialización de plantilla para sus entradas que dio como resultado el número de línea de esa plantilla. Estos fueron recolectados la primera vez a través del compilador y luego volcados en un archivo de código y el programa fue compilado nuevamente. Esa vez, cada ubicación en la que se usó la plantilla obtuvo un número diferente.

(hecho en D, por lo que podría no ser posible 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;
}

Una solución más sencilla sería mantener una ubicación estática y global de error " " 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

O sin el printf .. Solo incremente el error de ubicación cada vez que cruce un punto de rastreo. Luego, puede correlacionar el valor con la línea / número / versión escupida por sus compilaciones de depuración con bastante facilidad.

Necesitarías incluir la versión o el número de compilación, porque esas ubicaciones de error podrían cambiar con cualquier compilación.

No funciona bien si no puedes reproducir las rutas del código.

__FILE__ es un puntero al segmento de constantes de su programa. Si genera la diferencia entre esa y otra constante, debería obtener un resultado que sea independiente de cualquier reubicación, etc.:

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

Luego puedes informar eso, o combinarlo de alguna manera con el número de línea, etc. Los bits medios de FILE_STR_OFFSET son probablemente los más interesantes.

Bueno, si está mostrando el mensaje al usuario (en lugar de que el sistema muestre una dirección o función de bloqueo), no hay nada que le impida mostrar exactamente lo que desea.

Por ejemplo:

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 usarías como

buildErrorCodes(__FILE__, __LINE__, BUILD_CODE) 

y la salida en hexadecimal. No sería muy difícil de decodificar ...

(Editado: los comentaristas son correctos, debo haber estado loco para especificar 5 bits para el número de línea. Módulo 4096, sin embargo, las líneas con mensajes de error no pueden colisionar. 5 bits para la compilación aún están bien - Módulo 32 significa que solo 32 compilaciones pueden ser sobresalientes Y el error sigue ocurriendo en la misma línea.)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top