__FILE__, __LINE__ и __FUNCTION__ использование в С++

Предполагая, что ваш компилятор С++ поддерживает их, существует ли какая-либо особая причина не использовать __FILE__, __LINE__ и __FUNCTION__ для ведения журналов и отладки?

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

В принципе, могу ли я доверять __FILE__, __LINE__ и __FUNCTION__, чтобы всегда поступать правильно?

Ответ 1

__FUNCTION__ не является стандартным, __func__ существует в C99/С++ 11. Остальные (__LINE__ и __FILE__) просто хороши.

Он всегда будет сообщать правильный файл и строку (и функцию, если вы решите использовать __FUNCTION__/__func__). Оптимизация - это нефактор, так как это расширение макросов времени компиляции; он будет никогда влиять на производительность любым способом.

Ответ 2

В редких случаях может оказаться полезным изменить строку, заданную __LINE__ на что-то другое. Я видел, что GNU configure делает это для некоторых тестов, чтобы сообщить соответствующие номера строк после того, как он вставил некоторые вуду между строками, которые не отображаются в исходных исходных файлах. Например:

#line 100

__LINE__ следующие строки с __LINE__ 100. Вы можете дополнительно добавить новое имя файла

#line 100 "file.c"

Это редко бывает полезно. Но если это необходимо, нет никаких альтернатив, о которых я знаю. На самом деле, вместо линии, макрос может использоваться также, что должно привести к любой из двух вышеуказанных форм. Используя библиотеку препроцессора boost, вы можете увеличить текущую строку на 50:

#line BOOST_PP_ADD(__LINE__, 50)

Я подумал, что полезно упомянуть об этом, так как вы спрашивали об использовании __LINE__ и __FILE__. Из C++ никогда не бывает достаточно сюрпризов :)

Редактировать: @Jonathan Leffler предоставляет несколько замечаний в комментариях:

Мессинг С#line очень полезен для предварительных процессоров, которые хотят сохранить ошибки, сообщаемые в коде пользователя C, в соответствии с исходным файлом пользователя. Yacc, Lex, и (больше у меня дома). Препроцессоры ESQL/C делают это.

Ответ 3

FYI: g++ предлагает нестандартный макрос __PRETTY_FUNCTION__. До сих пор я не знал о C99 __func__ (спасибо Эван!). Я думаю, что по-прежнему предпочитаю __PRETTY_FUNCTION__, когда он доступен для определения дополнительного класса.

PS:

static string  getScopedClassMethod( string thePrettyFunction )
{
  size_t index = thePrettyFunction . find( "(" );
  if ( index == string::npos )
    return thePrettyFunction;  /* Degenerate case */

  thePrettyFunction . erase( index );

  index = thePrettyFunction . rfind( " " );
  if ( index == string::npos )
    return thePrettyFunction;  /* Degenerate case */

  thePrettyFunction . erase( 0, index + 1 );

  return thePrettyFunction;   /* The scoped class name. */
}

Ответ 4

Лично я не хочу использовать их ни для чего, кроме отладки сообщений. Я сделал это, но стараюсь не показывать такую ​​информацию клиентам или конечным пользователям. Мои клиенты - не инженеры, а иногда не компьютерные. Я могу записать эту информацию на консоль, но, как я сказал, неохотно за исключением отладочных сборников или внутренних инструментов. Я полагаю, что это зависит от вашей клиентской базы.

Ответ 5

Я использую их все время. Единственное, о чем я беспокоюсь, это отдать IP-адрес в файлах журналов. Если имена ваших функций действительно хороши, вы можете сделать коммерческую тайну легче раскрыть. Это похоже на отгрузку с отладочными символами, только сложнее найти вещи. В 99,999% случаев из этого ничего плохого не выйдет.