0

我是 C++ 调试技术的新手,我试图更好地理解添加代码只是为了调试目的。

当我使用这样的语句时:

#ifdef _DEBUG
cout << "Output that should only be used in Debugging Mode." << endl;
#endif 

其中的 cout 语句似乎总是在调试模式下运行和退出,我只希望该行仅在我处于调试模式时执行。这就是我认为这些类型的 if 语句的目的,除非我似乎误解了它的实际目的。

另外,有人可以详细说明CONSTRUCTOR_TRACEandFUNCTION_TRACE吗?它们究竟是用来做什么的,我该如何正确使用它们?

4

3 回答 3

2

#ifdef _DEBUG是一个编译时(实际上是预处理时)构造,它与您是否在调试器中执行程序无关,而是与_DEBUG定义宏的事实有关。

通常,您至少有两组构建选项,一组用于调试(定义_DEBUG、禁用多个编译器优化并生成调试符号),另一组用于发布(未定义_DEBUG、启用所有相关的编译器优化并且可能不生成调试信息,或在单独的文件中生成它们)。

当您开发程序时,您通常会使用调试配置,在构建可执行文件以最终部署/实际在日常使用中使用时,您将使用发布配置,其中不包括#ifdef _DEBUG ... #endif块中包含的代码。_DEBUG一旦在其中一种配置中生成可执行文件,它就会保持这种状态,在编译时定义的事实在可执行文件中“一成不变”。

话虽如此,有一些特定于平台的方法可以检测是否附加了调试器,但通常最好不要弄乱这些东西 - 根据是否附加了调试器来改变程序行为可能会破坏使用调试器的目的。


附录

好的,让我看看我是否完全理解。因此,如果我按 f5 运行调试构建,则此 #ifdef _DEBUG 中的任何内容都会被执行,并且当我按 ctrl+f5 以在发布模式下运行它时,它不会运行它所执行的 #ifdef _DEBUG 中的代码我。我不认为我完全明白你想说什么。如果可以的话,你能试着解释得简单一点。我在 c++ 和 Visual Studio 环境中没有那么先进。

在我看来,对于 C++ 中的构建/调试过程如何进行存在一些误解。当你点击F5时,会发生什么:

  1. 编译器被调用;它根据当前选择的配置的构建设置编译文件并生成可执行文件;1
  2. 运行可执行文件;
  3. VS 调试器附加到新创建的进程2

当您点击Ctrl+F5时,唯一的区别是跳过第 3 步;其余的完全一样。

现在,什么_DEBUG时候上场?在步骤 1,生成可执行文件(实际上,在步骤 1 的早期,在预处理阶段);无论调试器是否附加,它都没有区别 - 放入#ifdef _DEBUG块中的指令已经从可执行文件中写入(或排除)。

这里的重点是F5/ Ctrl+F5和Debug/Release配置是两个正交的设置;您可以构建“调试”可执行文件并在不调试的情况下启动它,并构建“发布”可执行文件并在调试时启动它(实际上,这通常用于调试仅在优化构建中出现的问题)。调试器附加到程序这一事实根本不应该改变其行为3

同样,开始有/没有调试器与您是否希望在此运行中附加调试器有关,在调试/发布配置中构建与实际构建可执行文件的方式有关(调试配置是更多“调试-友好”设置 -_DEBUG定义为启用调试代码,assert启用,禁用优化,启用调试符号,...)。


笔记

  1. 如果以前的构建中有一些可重用的输出,则跳过或缩短此步骤 - 例如,如果源没有更改上次构建的可执行文件并保留当前配置;
  2. 实际上,该进程是在附加调试器的情况下创建的;这可能会导致微妙的问题,但在这里不相关;
  3. 实际上,在某些情况下,调试器确实会改变其行为,因为进程可以使用 来检查调试器IsDebuggerPresent,但由于上述原因,通常您不想这样做。
于 2013-05-23T01:44:24.723 回答
1

我不认为“调试模式”意味着你认为它的作用。_DEBUG通常会在您编译调试版本时定义。编译后,无法进出“调试模式”。您可以在发布后编译并覆盖可执行文件,但是该二进制文件将成为发布版本,然后您将无法进入“调试模式”。

这与您是否使用调试器附加到应用程序,或者您的心态是“调试”还是“只是运行”无关。编译后,您可以假设它_DEBUG是永远定义的(如果您在调试模式下编译)或没有(否则) - 直到重新编译。

于 2013-05-23T01:42:26.017 回答
0

请交叉检查并确保未在您的发布项目配置中定义预处理器 _DEBUG。

如果您使用的是 Visual Studio,您可以在 Project Properties --> 选择 Configuration as Release 中进行检查,然后在 C++ --> Verify the Preprocessor --> Preprocessor Definitions 下进行检查。

#if _DEBUG

上面的#if 将检查是否定义了_DEBUG。如果定义了,那么它将执行下一个语句,如果没有定义,它将跳过下一个语句。

于 2013-05-23T12:22:55.240 回答