Манглинг __FILE__ и __LINE__ в коде для цитирования? - PullRequest
2 голосов
/ 27 сентября 2008

Есть ли способ получить препроцессор C / C ++ или шаблон или тому подобное для манипулирования / хэширования __FILE__ и __LINE__ и, возможно, некоторого другого внешнего ввода, такого как номер сборки, в один короткий номер, который можно заключать в кавычки в журналах или сообщения об ошибках?

(Предполагается, что он будет в состоянии перевернуть его (в список кандидатов, если он с потерями), когда это необходимо, когда клиент цитирует его в отчете об ошибке.)

Ответы [ 6 ]

2 голосов
/ 27 сентября 2008

Вам придется использовать функцию для выполнения хеширования и создания кода из __LINE__ и __FILE__, поскольку препроцессор C не может выполнять такие сложные задачи.

В любом случае, вы можете черпать вдохновение в этой статье , чтобы узнать, может ли другое решение лучше соответствовать вашей ситуации.

0 голосов
/ 04 октября 2008

__ FILE__ - указатель на сегмент констант вашей программы. Если вы выводите разницу между этой и некоторой другой константой, вы должны получить результат, независимый от любого перемещения, и т. Д .:

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

Затем вы можете сообщить об этом или каким-то образом объединить его с номером строки и т. Д. Средние биты FILE_STR_OFFSET, вероятно, наиболее интересны.

0 голосов
/ 27 сентября 2008

Более простым решением было бы сохранить глобальную статическую переменную "местоположение ошибки".

#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

Или без printf. Просто увеличивайте значение errloc при каждом пересечении точки трассировки. Затем вы можете легко соотнести значение с строкой / номером / версией, выпавшей из ваших отладочных сборок.

Вам нужно будет указать номер версии или сборки, потому что эти места ошибок могут измениться при любой сборке.

Не работает, если вы не можете воспроизвести пути кода.

0 голосов
/ 27 сентября 2008

Мне нужен был последовательный доступ в моем проекте, и я получил их, создав шаблон, который специализировался на __LINE__ и __FILE__ и привел к int, а также сгенерировал (как вывод времени компиляции в stdout) специализацию шаблона это входы, которые привели к номеру строки этого шаблона. Они были собраны в первый раз через компилятор и затем выгружены в файл кода, и программа была скомпилирована снова. Тогда каждое местоположение, в котором использовался шаблон, получало разные номера.

(сделано в D, поэтому в 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;
}
0 голосов
/ 27 сентября 2008

Ну ... вы можете использовать что-то вроде:

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

Это не было бы совершенно уникально, но это могло бы работать для того, что вы хотите. Может изменить эти OR на +, что может работать лучше для некоторых вещей.

Естественно, если вы действительно можете создать хеш-код, вы, вероятно, захотите это сделать.

0 голосов
/ 27 сентября 2008

Ну, если вы сами выводите сообщение пользователю (в отличие от того, чтобы система отображала адрес сбоя или функцию), ничто не мешает вам отображать именно то, что вы хотите.

Например:

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

Вы бы использовали это как

buildErrorCodes(__FILE__, __LINE__, BUILD_CODE) 

и выведите его в шестнадцатеричном виде. Не было бы очень трудно расшифровать ...

(Отредактировано - комментаторы верны, я, должно быть, сошел с ума, чтобы указать 5 бит для номера строки. Однако по модулю 4096 строки с сообщениями об ошибках вряд ли будут конфликтовать. 5 бит для сборки все еще в порядке - Модуль 32 означает, что только 32 сборки могут быть выдающимися, и ошибка все равно будет возникать в одной строке.)

...