仅在调试模式下的控制台输出 c++

Console output only in debug mode c++

我本以为这会是一个被广泛问到的问题,但我仍然没有找到答案。

我正在调试一些 C++ 代码,这些代码仅在将某些函数句柄作为输入时以微妙的方式产生错误。长话短说解决了问题,但我在 .cpp 文件中定义:

#define DEBUG(x) do { std::cerr << x << std::endl; } while (0)

不用说代码中到处都是:

DEBUG("Foo's address") 
DEBUG(&Foo)

现在我假设在 "Release" 中编译器将忽略所有这些预编译器输出。但事实并非如此!

那么在实践中如何做到这一点(我想保留输出以供将来添加,但显然不希望在发布版本中使用)?我正在尝试使用 cmake 的 clion,这是 IDE/compiler 特定的吗?

谢谢

根据你的编译器,它可能会定义一些东西告诉你编译处于调试模式(或者你可以在命令行上自己做),然后:

#ifndef _DEBUG // works in VS
#define DEBUG(x) 
#else
#define DEBUG(x) do { std::cerr << x << std::endl; } while (0)
#endif

有关使用哪个宏的更多讨论,请参阅 this 问题。

执行此操作的便携式方法是使用 NDEBUG

#ifdef NDEBUG
#define DEBUG(x) 
#else
#define DEBUG(x) do { std::cerr << x << std::endl; } while (0)
#endif

参见:C / C++ : Portable way to detect debug / release?

在所谓的 "release versions" 中消除日志消息通常是错误的。毕竟,"release versions" 是您最需要记录信息的地方!当最终用户只会告诉您 "it doesn't work" 或“它崩溃了 时,您还希望如何分析和解决问题? "?

因此,与其消除您的软件为帮助您修复错误而创建的有价值的信息,不如考虑如何保存和保留这些信息,以便在出现问题时最终用户可以轻松地将其传输给您。例如,当应用程序在用户机器上运行时,将日志消息重定向到日志文件(也许应用程序本身提供 "Send log file to support" 功能,或类似的东西)。

代码类似

DEBUG("Foo's address") 
DEBUG(&Foo)

应替换为:

Log("Foo's address");
Log(std::to_string(&Foo));

然后在你的 Log 函数中,它可能有一个像 void Log(std::string const& message) 这样的签名,你可以检查你的 DEBUG 宏并采取相应的行动:

    void Log(std::string const& message)
    {
#ifdef DEBUG
        // write message to std::cerr
#else
        // write message to log file
#endif
    }

现在,DEBUG 当然 不是标准宏 (与 NDEBUG 不同,后者会打开和关闭 assert)。它不是隐式定义的。您必须在调用编译器时自己定义它。例如,/DDEBUG 与 MSVC 或 -DDEBUG 与 GCC。有可能你的 IDE 在运行编译器时添加了这样一个标志,或者类似 -D_DEBUG 的东西,但这仍然不是标准的,也不是编译器本身的一部分。 (实际上,如果您要像这样使用它,您可能会考虑为宏起一个不同的名称,例如 LOG_TO_CONSOLE。)

无论如何,这只是为了让您了解如何做。您可能更喜欢基于 std::ostream 的方法,而不是采用 std::string 的函数。 Whosebug上有很多关于这个的问答。

重要的一点是:不要假设一旦您的软件发布就不需要它,就不要丢弃有价值的日志信息。会有bug和模糊的错误描述。