在C++中__FILE __,_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

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__).优化是一个非因素,因为它是一个编译时宏扩展; 它绝不会以任何方式影响性能.

  • `__func__`现在是C++ 11标准. (33认同)
  • 人们不禁想知道为什么他们选择不将其称为“__FUNC__”以保持一致,或者为什么他们不只是将“__FUNCTION__”添加到C++11标准而不是“__func__” (4认同)
  • @thr:虽然你提出了一个很好的观点.我很清楚c99中存在`__func__`,而不是c ++.无论如何,我认为在c ++中合理实现`__func__`只会导致错误的名称.因为我不是编译器编写者,所以不是我的电话. (3认同)
  • `__func__`是C++中的一个问题.C99没有说出关于默认参数等等的一个词,在这种情况下,`__func__`在C++中的表现并不是那么明显. (2认同)

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)

  • 很高兴知道 \_\_PRETTY_FUNCTION\_\_。很有用! (2认同)

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__ 之间有什么区别?

  • 当前的 gcc-9 中有 `&lt;experimental/source_location&gt;`。 (2认同)

Cra*_*g S 7

就个人而言,我不愿意将这些用于调试消息.我已经做到了,但我尽量不向客户或最终用户展示这种信息.我的客户不是工程师,有时不精通计算机.我可能会将此信息记录到控制台,但正如我所说,除了调试版本或内部工具之外,我不情愿.不过,我认为这取决于您拥有的客户群.

  • "我可能会将此信息记录到控制台" - 或者更好:将其记录到文件中,这样如果出现问题,您可以要求客户将其发送给您... (27认同)
  • @Christoph ...并且不要忘记定期缩小、删除或覆盖此类文件。否则,客户可能想知道为什么有一天她/他的磁盘已满......:-) (2认同)

Jef*_*ter 5

我一直都在用它们。我唯一担心的是在日志文件中放弃IP。如果您的函数名称确实不错,那么您可能会更容易发现商业秘密。有点像附带调试符号,只是很难找到东西。在99.999%的情况下,不会有不好的结果。