Использование __FILE__, __LINE__ и __FUNCTION__ в C ++ - PullRequest
142 голосов
/ 28 февраля 2009

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

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

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

Ответы [ 5 ]

170 голосов
/ 28 февраля 2009

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

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

36 голосов
/ 28 февраля 2009

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

#line 100

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

#line 100 "file.c"

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

#line BOOST_PP_ADD(__LINE__, 50)

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

Редактировать: @Джонатан Леффлер приводит еще несколько хороших примеров использования в комментариях:

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

28 голосов
/ 28 февраля 2009

К вашему сведению: 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. */
}
7 голосов
/ 28 февраля 2009

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

5 голосов
/ 05 февраля 2015

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

...