__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% случаев из этого ничего плохого не выйдет.