Run*_*ble 149 c++ debugging logging c-preprocessor
假设您的C++编译器支持它们,是否有任何特殊原因不使用__FILE__,__LINE__以及__FUNCTION__用于记录和调试目的?
我主要关注的是为用户提供误导性数据 - 例如,由于优化而报告错误的行号或功能,或者因此导致性能下降.
基本上,我可以信任__FILE__,__LINE__并__FUNCTION__以永远做正确的事?
Eva*_*ran 181
__FUNCTION__是非标准的,__func__存在于C99/C++ 11中.其他人(__LINE__和__FILE__)就好了.
它将始终报告正确的文件和行(如果您选择使用__FUNCTION__/,则为函数__func__).优化是一个非因素,因为它是一个编译时宏扩展; 它绝不会以任何方式影响性能.
Joh*_*itb 37
在极少数情况下,更改由__LINE__其他内容给出的行可能很有用.我已经看到GNU configure为某些测试报告了适当的行号,它在原始源文件中没有出现的行之间插入了一些伏都教.例如:
#line 100
Run Code Online (Sandbox Code Playgroud)
将使以下行以__LINE__100 开头.您可以选择添加新文件名
#line 100 "file.c"
Run Code Online (Sandbox Code Playgroud)
它很少有用.但如果需要,我知道没有其他选择.实际上,也可以使用宏来代替行,这必须导致上述两种形式中的任何一种.使用boost预处理器库,您可以将当前行增加50:
#line BOOST_PP_ADD(__LINE__, 50)
Run Code Online (Sandbox Code Playgroud)
我认为提及它是有用的,因为你问__LINE__及和的用法__FILE__.一个人从来没有从C++中获得足够的惊喜:)
编辑: @Jonathan Leffler在评论中提供了一些更好的用例:
与#line混淆对于希望将用户的C代码中报告的错误与用户的源文件保持一致的预处理器非常有用.Yacc,Lex和(更多在我家)ESQL/C预处理器就是这么做的.
Mr.*_*Ree 28
仅供参考:g ++提供非标准__PRETTY_FUNCTION__宏.直到现在我还不知道C99 __func__(谢谢Evan!).我认为当它可用于额外的类范围时,我仍然更喜欢__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. */
}
Run Code Online (Sandbox Code Playgroud)
Cir*_*四事件 13
C++20 std::source_location
C++ 终于添加了一个非宏选项,当 C++20 普及时,它可能会在未来的某个时候占据主导地位:
文档说:
constexpr const char* function_name() const noexcept;
6 返回:如果此对象表示函数体中的一个位置,则返回一个实现定义的 NTBS,该 NTBS 应与函数名称相对应。否则,返回一个空字符串。
其中 NTBS 表示“空终止字节字符串”。
当支持到达 GCC 时,我会尝试一下,GCC 9.1.0g++-9 -std=c++2a仍然不支持它。
https://en.cppreference.com/w/cpp/utility/source_location声明用法如下:
#include <iostream>
#include <string_view>
#include <source_location>
void log(std::string_view message,
const 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!");
}
Run Code Online (Sandbox Code Playgroud)
可能的输出:
info:main.cpp:16:main Hello world!
Run Code Online (Sandbox Code Playgroud)
__PRETTY_FUNCTION__对比__FUNCTION__对比__func__对比std::source_location::function_name
回答:__PRETTY_FUNCTION__、__FUNCTION__、__func__ 之间有什么区别?
就个人而言,我不愿意将这些用于调试消息.我已经做到了,但我尽量不向客户或最终用户展示这种信息.我的客户不是工程师,有时不精通计算机.我可能会将此信息记录到控制台,但正如我所说,除了调试版本或内部工具之外,我不情愿.不过,我认为这取决于您拥有的客户群.
我一直都在用它们。我唯一担心的是在日志文件中放弃IP。如果您的函数名称确实不错,那么您可能会更容易发现商业秘密。有点像附带调试符号,只是很难找到东西。在99.999%的情况下,不会有不好的结果。