C ++:为什么必须在第一行中设置调试模式?

时间:2019-04-07 00:25:16

标签: c++ gcc g++

我正在以下无用的程序中在gcc中设置调试模式:

MyResource

,该程序让我知道我的索引越界。但是,如果翻转前两行的顺序,则不会收到此类错误消息(在#define之前#include)。为什么是这样?有没有办法在程序的另一行切换调试模式(没有编译器标志)?我问是因为我正在Leetcode.com上解决问题,在这里我无法通过编译器标志或修改问题的第一行。

2 个答案:

答案 0 :(得分:3)

  

为什么必须在第一行中设置调试模式?

因为受宏影响的是标准库头。如果您之前包含标头,则包含的定义将看不到宏定义。考虑以下示例,并假设它是标准标头中包含的函数定义:

#define _GLIBCXX_DEBUG 1

inline void foo() {
#ifdef _GLIBCXX_DEBUG
    std::cout  << "debug mode is enabled";
#else
    std::cout  << "debug mode is not enabled";
#endif
}

与之相对:

inline void foo() {
#ifdef _GLIBCXX_DEBUG
    std::cout  << "debug mode is enabled";
#else
    std::cout  << "debug mode is not enabled";
#endif
}

#define _GLIBCXX_DEBUG 1
  

有没有办法在程序的另一行上切换调试模式(没有编译器标志)?

不包括标准标头。

在这种情况下,您可以使用std::vector::at代替下标运算符。即使没有调试模式,它也会诊断超出范围的访问。

答案 1 :(得分:2)

任何以#…开头的内容都是对C++ preprocessor的一条指令,该指令在实际的C / C ++编译器的之前运行;预处理程序为编译器构造最终的源代码。

这就是程序编译时发生的事情。

第一步:预处理

预处理器自上而下读取代码并执行指令。

#define _GLIBCXX_DEBUG 1

将名为_GLIBCXX_DEBUG的标志设置为1

#include <vector>
#include <iostream>

从编译器的包含路径中读取文件vector.hiostream.h。该文件包含更多的C / C ++代码以及预处理器指令,这些指令现在以递归方式展开。某些代码可能看起来像

#if _CLIBCXX_DEBUG
prinf("Print me to debug!");
#endif

,此代码将显示在最终的C / C ++中。如果您的_CLIBCXX_DEBUG0,则代码将不存在。最终结果是您可以在编译之前将代码放在一起。

在您的情况下,额外的代码将特殊测试添加到最终的C / C ++文件中,这会导致您看到错误消息。当您切换线路时,处理#include时不会设置该标志,因此不会将这些特殊测试添加到您的源中。

有关如何转储最终正在编译的最终C / C ++代码的信息,请参见this question

第二步:编译

一旦对C / C ++源代码文件进行了预处理(例如,包含了东西,有条件地展开等),然后将调用实际的编译器来构建代码。

  

有没有办法在程序的另一行上切换调试模式(没有编译器标志)?

根据需要在整个代码中更改该标志的值。