我在以下无用的程序中在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上解决问题,我无法传递编译器标志或修改问题的第一行。
为什么必须在第一行设置调试模式?
因为它是受宏影响的标准库头。如果之前包含标题,则包含的定义将不会看到宏定义。请考虑以下示例,并假设它是标准头中包含的函数定义:
#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
而不是下标运算符。即使没有调试模式,它也会诊断出越界访问。
以#…
开头的任何内容都是对C++ preprocessor的指令,它在实际的C / C ++编译器之前运行;预处理器构造编译器的最终源代码。
所以这是你的程序编译时发生的事情。
预处理器自上而下读取代码并执行指令。
#define _GLIBCXX_DEBUG 1
将一个名为_GLIBCXX_DEBUG
的旗帜设置为1
。
#include <vector>
#include <iostream>
从编译器的包含路径中读取文件vector.h
和iostream.h
。该文件包含更多的C / C ++代码以及现在递归展开的预处理器指令。其中一些代码可能看起来像
#if _CLIBCXX_DEBUG
prinf("Print me to debug!");
#endif
并且此代码显示在最终的C / C ++中。如果你的_CLIBCXX_DEBUG
是0
那么代码就不会存在。实际效果是您可以在编译之前将代码放在一起。
在您的情况下,额外的代码会在您的最终C / C ++文件中添加特殊测试,这会导致您看到的错误消息。切换线时,处理#include
时不会设置标志,因此这些特殊测试不会添加到源中。
有关如何转储实际正在编译的最终C / C ++代码,请参阅this question。
一旦您的C / C ++源代码文件被预处理(即包含的东西,有条件地展开等等),然后调用实际的编译器来构建您的代码。
有没有办法在程序中的另一行切换调试模式(没有编译器标志)?
根据需要在整个代码中更改该标志的值。