C++ 中 __FILE__、__LINE__ 和 __FUNCTION__ 的用法

问题描述 投票:0回答:6

假设您的 C++ 编译器支持它们,是否有任何特殊原因使用

__FILE__
__LINE__
__FUNCTION__
进行日志记录和调试?

我主要关心的是向用户提供误导性数据,例如,由于优化而报告错误的行号或函数,或者导致性能下降。

基本上,我可以相信

__FILE__
__LINE__
__FUNCTION__
永远做正确的事吗?

c++ debugging logging c-preprocessor
6个回答
231
投票

__FUNCTION__
是非标准的,
__func__
存在于 C99 / C++11 中。其他(
__LINE__
__FILE__
)都很好。

它将始终报告正确的文件和行(如果您选择使用

__FUNCTION__
/
__func__
,则可以运行)。优化不是一个因素,因为它是编译时宏扩展;它永远不会以任何方式影响性能。


40
投票
__LINE__

给出的行更改为其他内容可能会很有用。我见过 GNU 配置 在某些测试中这样做,在原始源文件中未出现的行之间插入一些巫术后报告适当的行号。例如:


#line 100

将使以下行以 
__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 预处理器就是这样做的。


33
投票
C++20

std::source_location


C++ 终于添加了一个非宏选项,当 C++20 广泛普及时,它可能会在未来某个时候占据主导地位:

    https://en.cppreference.com/w/cpp/utility/source_location
  • http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1208r5.pdf
  • 文档说:

constexpr const char* function_name() const noexcept;

6 返回:如果该对象代表函数体内的一个位置, 返回一个实现定义的 NTBS,它应该对应于 函数名称。否则,返回空字符串。

其中 NTBS 表示“空终止字节字符串”。

该功能在 GCC 11.2 Ubuntu 21.10 上具有

-std=c++20

。它不在 GCC 9.1.0 上,带有

g++-9 -std=c++2a

https://en.cppreference.com/w/cpp/utility/source_location

显示用法是: 主.cpp

#include <iostream> #include <string_view> #include <source_location> void log(std::string_view message, std::source_location location = std::source_location::current() ) { std::cout << "info:" << location.file_name() << ":" << location.line() << ":" << location.function_name() << " " << message << '\n'; } int main() { log("Hello world!"); }

编译并运行:

g++ -std=c++20 -Wall -Wextra -pedantic -o main.out main.cpp ./main.out

输出:

info:main.cpp:17:int main() Hello world!

__PRETTY_FUNCTION__ vs

__FUNCTION__
vs
__func__
vs
std::source_location::function_name

回答于:

__PRETTY_FUNCTION__、__FUNCTION__、__func__ 有什么区别?


32
投票

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
投票


4
投票

© www.soinside.com 2019 - 2024. All rights reserved.