为什么必须在第一行设置_GLIBCXX_DEBUG?

问题描述 投票:1回答:2

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

#define _GLIBCXX_DEBUG 1
#include <vector>
#include <iostream>
using namespace std;
int main() {
    vector<int> v{1,2,3};
    for(int i=0; i<100000000000000;i++)
    cout<<v[i];
}

程序让我知道我的索引超出范围。但是,如果我翻转前两行的顺序,我得不到这样的错误消息(#define之前的#include)。为什么是这样?有没有办法在程序中的另一行切换调试模式(没有编译器标志)?我问,因为我在Leetcode.com上解决问题,我无法传递编译器标志或修改问题的第一行。

c++ gcc g++
2个回答
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而不是下标运算符。即使没有调试模式,它也会诊断出越界访问。


2
投票

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

所以这是你的程序编译时发生的事情。

Step one: preprocess

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

#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

Step two: compile

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

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

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

© www.soinside.com 2019 - 2024. All rights reserved.