在调试模式下工作

Working in debugging mode

本文关键字:工作 模式 调试      更新时间:2023-10-16

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

当我使用这样的语句时:

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

内的cout语句似乎总是在调试模式中运行和退出,我只希望这一行只在调试模式中执行。这就是我认为这些if语句的目的,除非我似乎误解了它的实际目的。

另外,有人能详细说明CONSTRUCTOR_TRACEFUNCTION_TRACE吗?它们的确切用途是什么,我如何正确使用它们?

#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和调试/释放配置是两个正交设置;您可以构建一个"调试"可执行文件并在没有调试的情况下启动它,也可以构建一个"发布"可执行文件并在调试的情况下启动它(实际上,这通常是为了调试只在优化构建中出现的问题)。将调试器附加到程序上的事实根本不应该改变程序的行为3

再次强调,在启动/不启动调试器与你是否想要在运行中附加一个调试器有关,在调试/发布配置中构建与可执行文件的实际构建方式有关(调试配置是一个更"调试友好"设置的集合- _DEBUG定义为启用调试代码,assert启用,优化禁用,调试符号启用,…)。


指出

  1. 如果从以前的构建中有一些可重用的输出,则跳过或缩短此步骤-例如,如果源没有更改上次构建的可执行文件,并保留当前配置;
  2. 实际上,进程是附带调试器创建的;这个可以引起微妙的问题,但在这里不相关;
  3. 实际上,在某些情况下,调试器确实改变了它的行为,因为进程可以使用IsDebuggerPresent检查调试器,但通常您不想这样做,原因如上所述。

我不认为"调试模式"意味着你认为它的作用。_DEBUG通常在编译调试版本时定义。编译完成后,没有办法进入和退出"调试模式"。你可以在发行版中编译,然后覆盖可执行文件,但这样二进制文件就会成为发行版,这样你就不能进入"调试模式"了。

这与你是否使用调试器连接到应用程序无关,也与你的心态是"调试"还是"运行"无关。编译完成后,可以假设_DEBUG是永远定义的(如果在调试模式下编译),或者没有定义(否则)——直到重新编译。

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

如果你使用的是Visual studio,你可以在Project Properties ->选择Configuration作为Release,然后在c++ -> Verify the Preprocessor -> Preprocessor Definitions中检查。

#if _DEBUG

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