#ifdef _DEBUG
是一个编译时(实际上是预处理时)构造,它与您是否在调试器中执行程序无关,而是与_DEBUG
定义宏的事实有关。
通常,您至少有两组构建选项,一组用于调试(定义_DEBUG
、禁用多个编译器优化并生成调试符号),另一组用于发布(未定义_DEBUG
、启用所有相关的编译器优化并且可能不生成调试信息,或在单独的文件中生成它们)。
当您开发程序时,您通常会使用调试配置,在构建可执行文件以最终部署/实际在日常使用中使用时,您将使用发布配置,其中不包括#ifdef _DEBUG ... #endif
块中包含的代码。_DEBUG
一旦在其中一种配置中生成可执行文件,它就会保持这种状态,在编译时定义的事实在可执行文件中“一成不变”。
话虽如此,有一些特定于平台的方法可以检测是否附加了调试器,但通常最好不要弄乱这些东西 - 根据是否附加了调试器来改变程序行为可能会破坏使用调试器的目的。
附录
好的,让我看看我是否完全理解。因此,如果我按 f5 运行调试构建,则此 #ifdef _DEBUG 中的任何内容都会被执行,并且当我按 ctrl+f5 以在发布模式下运行它时,它不会运行它所执行的 #ifdef _DEBUG 中的代码我。我不认为我完全明白你想说什么。如果可以的话,你能试着解释得简单一点。我在 c++ 和 Visual Studio 环境中没有那么先进。
在我看来,对于 C++ 中的构建/调试过程如何进行存在一些误解。当你点击F5时,会发生什么:
- 编译器被调用;它根据当前选择的配置的构建设置编译文件并生成可执行文件;1
- 运行可执行文件;
- VS 调试器附加到新创建的进程2。
当您点击Ctrl+F5时,唯一的区别是跳过第 3 步;其余的完全一样。
现在,什么_DEBUG
时候上场?在步骤 1,生成可执行文件(实际上,在步骤 1 的早期,在预处理阶段);无论调试器是否附加,它都没有区别 - 放入#ifdef _DEBUG
块中的指令已经从可执行文件中写入(或排除)。
这里的重点是F5/ Ctrl+F5和Debug/Release配置是两个正交的设置;您可以构建“调试”可执行文件并在不调试的情况下启动它,并构建“发布”可执行文件并在调试时启动它(实际上,这通常用于调试仅在优化构建中出现的问题)。调试器附加到程序这一事实根本不应该改变其行为3。
同样,开始有/没有调试器与您是否希望在此运行中附加调试器有关,在调试/发布配置中构建与实际构建可执行文件的方式有关(调试配置是更多“调试-友好”设置 -_DEBUG
定义为启用调试代码,assert
启用,禁用优化,启用调试符号,...)。
笔记
- 如果以前的构建中有一些可重用的输出,则跳过或缩短此步骤 - 例如,如果源没有更改上次构建的可执行文件并保留当前配置;
- 实际上,该进程是在附加调试器的情况下创建的;这可能会导致微妙的问题,但在这里不相关;
- 实际上,在某些情况下,调试器确实会改变其行为,因为进程可以使用 来检查调试器
IsDebuggerPresent
,但由于上述原因,通常您不想这样做。