Изменение __FILE__ и __LINE__ в коде для цитирования?

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

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

Вы думаете, что у пользователей возникнут проблемы с цитированием «файл + строка», но они смогут дать вам хэш без транспонирования цифр?

Shog9 27.09.2008 02:06

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

Jonathan Leffler 19.10.2008 11:02
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
2
2 368
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

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

Например:

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 сборки могут быть невыполненными, И ошибка по-прежнему возникает в той же строке.)

У вас должны быть очень короткие исходные файлы для ЛИНИЯ, чтобы поместиться в 5 бит.

Michael Burr 27.09.2008 02:24

Он предлагает C / C++, но его собственные проекты могут быть написаны на Python (следовательно, требуется очень мало кода :) Шучу, конечно, комментарий Майка Б. уместен. Майк Джи, тебе следует пересмотреть свой ответ.

tzot 27.09.2008 03:37

Вы оба абсолютно правы. Отредактировано, чтобы сделать строку 12 бит, а не 5, и явно модулировать строку #.

Mike G. 09.10.2008 01:04
Ответ принят как подходящий

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

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

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

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

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

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

Здесь есть пара проблем. В основном вы используете && (логическое и), когда вы имеете в виду & (побитовое И), и все файлы, строковые константы которых находятся в пределах 64 КБ (что может быть большим числом в зависимости от компилятора), будут иметь одинаковые верхние биты. Средние биты более интересны.

Frank Szczerba 04.10.2008 01:07

Мне потребовались серийные значения в моем проекте, и я получил их, создав шаблон, который специализировался на __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;
}

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

#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 каждый раз, когда пересекаете точку трассировки. Затем вы можете легко сопоставить значение со строкой / номером / версией, выдаваемой вашими отладочными сборками.

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

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

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

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

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

Другие вопросы по теме