Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/57.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/39.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
当指定-g时,gcc定义了什么吗?_C_Debugging_Gcc_C Preprocessor - Fatal编程技术网

当指定-g时,gcc定义了什么吗?

当指定-g时,gcc定义了什么吗?,c,debugging,gcc,c-preprocessor,C,Debugging,Gcc,C Preprocessor,简而言之,我想知道如果启用了-g,gcc(或g++。我在C中需要它,但也对C++)是否定义了任何特殊符号。是吗?如果是,什么符号 在搜索过程中,我发现: \u DEBUG是手动定义的(我所说的手动是指-D_DEBUG),这是Visual C程序员的习惯(因为VC在调试模式下编译时定义\u DEBUG) 如果未处于调试模式,则定义NDEBUG。虽然我在一些地方发现了这样的说法,但我尝试在.c和.cpp文件中使用我的gcc和g++,无论是否使用-g都没有定义这样的符号 编辑:让我演示一下我不想使

简而言之,我想知道如果启用了
-g
,gcc(或g++。我在C中需要它,但也对C++)是否定义了任何特殊符号。是吗?如果是,什么符号

在搜索过程中,我发现:

  • \u DEBUG
    是手动定义的(我所说的手动是指
    -D_DEBUG
    ),这是Visual C程序员的习惯(因为VC在调试模式下编译时定义
    \u DEBUG
  • 如果未处于调试模式,则定义
    NDEBUG
    。虽然我在一些地方发现了这样的说法,但我尝试在.c和.cpp文件中使用我的gcc和g++,无论是否使用
    -g
    都没有定义这样的符号
编辑:让我演示一下我不想使用非标准符号的原因:

想象一下,一个内核模块做了一些事情,还提供了要包含在其他内核模块中的头文件,以便它们可以连接到这个模块

现在作为一个工具,在我的一个头文件中:

#ifdef DEBUG <-- This is what I need
#define LOG(x, ...) printk("Some extra info"x, ##__VA_ARGS__);
#else
#define LOG(x, ...) printk("Without extra info"x, ##__VA_ARGS__);
#endif
用法:

#include "how_to_build.h"

#ifdef MY_DEBUG
// rest of the story

这样,
NDEBUG
的公共选项也会删除我的定义。如果他们不想在调试模式下获取头文件,仍然需要我告诉他们如何定义它。

您可以看到所有宏的列表gcc/g++定义的任意标志组合,如:

$ g++ -E -dD -xc++ /dev/null
例如:

[max@truth ~]$ g++ -E -dD -xc++ /dev/null > a
[max@truth ~]$ g++ -E -dD -xc++ -g -O3 /dev/null > b
[max@truth ~]$ diff a b
1a2
> # 1 "/home/max//"
173c174
< #define __NO_INLINE__ 1
---
> #define __OPTIMIZE__ 1
额外的预处理器指令,但没有用于
-g
标志的额外宏


这很有意义:
-g
对代码生成没有影响,只对对象文件元数据(调试符号)有影响

-O0
是一致调试的“调试模式”代码生成器,与
-Og
或更高版本相反。(更详细地解释了这对gcc和clang之类的编译器意味着什么:在每条语句之后将所有变量存储回它们的内存位置,而不要跨语句进行优化。)

-O3
-g
是正交的(除了在调试优化代码时对某些变量进行了“优化”,并且执行似乎在源代码行之间跳跃。)

运行
g++-E-dD-xc++/dev/null

vs.
g++-E-dD-g-xc++/dev/null

没有显示额外定义的符号


这一点,再加上缺乏任何说明符号已定义的文档,应该足以安全地说什么也没有定义。

正如其他人所说,从中可以明显看出,GCC不提供任何指示是否将生成调试信息的内在宏(
-g
模式)。我想补充的是,这是故意的

很久很久以前,GCC的原始作者(RMS、Kenner,可能还有其他几位)决定,启用调试信息不应导致对实际代码的任何更改,以降低出现错误的风险。这是GCC中最基本的设计原则,即使在今天,开发人员也会不遗余力地维护它


定义宏将违反此设计原则,因为它将允许源代码根据
-g

改变自身。最佳做法是始终使用
-g
,因为它不会影响优化的代码或使其变慢。此外,在Unix上,标准的做法是将
NDEBUG
define传递给编译器进行发布版本,而不为调试定义任何内容。因此,您应该考虑使用<代码> NDECUG/<代码>定义来告诉调试从发布构建。@ MaximYegorushkin,它是标准的还是仅仅是约定?如果它是标准的,为什么gcc不会自动执行呢?这是一个标准约定。C/C++语言不需要定义这些符号。NDEBUG使assert.h的行为不同,这是标准的。“顺便说一句,要在调试模式下获取头,请定义另一个符号”是标准的方法,IMO。非常有用的答案,很好地理解了这方面的背景。
[max@truth ~]$ g++ -E -dD -xc++ /dev/null > a
[max@truth ~]$ g++ -E -dD -xc++ -g -O3 /dev/null > b
[max@truth ~]$ diff a b
1a2
> # 1 "/home/max//"
173c174
< #define __NO_INLINE__ 1
---
> #define __OPTIMIZE__ 1
[max@truth ~]$ g++ -E -dD -xc++ -g /dev/null > c
[max@truth ~]$ diff a c
1a2
> # 1 "/home/max//"