C++ gcc -g :会发生什么

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5179202/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 17:36:28  来源:igfitidea点击:

gcc -g :what will happen

c++cgccgdb

提问by Vijay

This question was asked to me in an interview.

这个问题是在一次采访中被问到的。

they asked me how to generate a core dump file with which i can debug. then i said that with -gflag in gccwe can do it.

他们问我如何生成一个我可以调试的核心转储文件。然后我说有了-gflaggcc我们就可以做到。

then they have asked me what exactly does that -gflag do to the compiler.

然后他们问我那个-g标志到底对编译器做了什么。

i said (probably a wrong answer) that it will open up all the symbols in the core file which can be used for debugging.

我说(可能是错误的答案)它将打开核心文件中可用于调试的所有符号。

can anyone tell me what exactly does it do?

谁能告诉我它到底是做什么的?

回答by Tony Delroy

That's kind of right, but incomplete. -grequests that the compiler and linker generate and retain source-level debugging/symbol information in the executable itself.

这有点对,但不完整。 -g要求编译器和链接器在可执行文件本身中生成并保留源代码级调试/符号信息。

If...

如果...

  • the program happens to later crash and produce a core file (which suggests some problem in the actual code), or
  • a deliberate OS command forced it to core (e.g. kill -SIGQUITpid), or
  • the program calls a function that dumps core (e.g. abort)
  • 程序碰巧后来崩溃并产生一个核心文件(这表明实际代码中存在一些问题),或
  • 一个故意的操作系统命令强迫它成为核心(例如kill -SIGQUITpid),或
  • 程序调用一个转储核心的函数(例如abort

...- none of which are actually caused by the use of -g- then the debugger will know how to read that "-g" symbol information from the executable and cross-reference it with the core. This means you can see the proper names of variables and functions in your stack frames, get line numbers and see the source as you step around in the executable.

...-实际上没有一个是由使用引起的-g-然后调试器将知道如何-g从可执行文件中读取“ ”符号信息并将其与核心交叉引用。这意味着您可以在堆栈帧中看到变量和函数的正确名称,获取行号并在执行可执行文件时查看源代码。

That debug information is useful whenever debugging - whether you started with a core or just the executable alone. It even helps produce better output from commands like pstack.

调试信息在调试时很有用 - 无论您是从核心开始还是仅从可执行文件开始。它甚至有助于从诸如pstack.

Note that your environment may have other settings to control whether cores are generated (they can be big, and there's no general way to know if/when they can be removed, so they're not always wanted). For example, on UNIX/LINUX shells it's often ulimit -c.

请注意,您的环境可能有其他设置来控制是否生成内核(它们可能很大,并且没有通用的方法来知道它们是否/何时可以被删除,因此并不总是需要它们)。例如,在 UNIX/LINUX shell 上,它通常是ulimit -c.

You may also be interested to read about DWARFWikipedia- a commonly used debugging information format for encoding the embedded debug/symbol information in executable/library objects (e.g. on UNIX and Linux).

您可能也有兴趣阅读DWARF维基百科- 一种常用的调试信息格式,用于在可执行文件/库对象(例如在 UNIX 和 Linux 上)中对嵌入的调试/符号信息进行编码。

UPDATE per Victor's request in comments...

根据维克多在评论中的要求更新......

Symbol informationlists identifiers from the source code (usually only after any name manglingneeded), the (virtual) memory addresses/offsets at which they'll be loaded in the process memory, the type (e.g. data vs. code). For example...

符号信息列出了源代码中的标识符(通常只在需要进行任何名称修改之后)、(虚拟)内存地址/偏移量(虚拟)将在进程内存中加载的位置、类型(例如数据与代码)。例如...

$ cat ok.cc
int g_my_num;
namespace NS { int ns_my_num = 2; }
int f() { return g_my_num + NS::ns_my_num; }
int main() { return f(); }

$ g++ -g ok.cc -o ok    # compile ok executable with symbol info

$ nm ok    # show mangled identifiers
00000000004017c8 d _DYNAMIC
0000000000401960 d _GLOBAL_OFFSET_TABLE_
0000000000400478 R _IO_stdin_used
                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
                 w _Jv_RegisterClasses
000000000040037c T _Z1fv                     # this is f()
0000000000401798 D _ZN2NS9ns_my_numE         # this is NS::ns_my_num
00000000004017a8 d __CTOR_END__
00000000004017a0 d __CTOR_LIST__
00000000004017b8 d __DTOR_END__
00000000004017b0 d __DTOR_LIST__
0000000000400540 r __FRAME_END__
00000000004017c0 d __JCR_END__
00000000004017c0 d __JCR_LIST__
00000000004017c8 d __TMC_END__
00000000004017c8 d __TMC_LIST__
0000000000401980 A __bss_start
0000000000401788 D __data_start
0000000000400440 t __do_global_ctors_aux
00000000004002e0 t __do_global_dtors_aux
0000000000401790 d __dso_handle
0000000000000000 a __fini_array_end
0000000000000000 a __fini_array_start
                 w __gmon_start__
0000000000000000 a __init_array_end
0000000000000000 a __init_array_start
00000000004003a0 T __libc_csu_fini
00000000004003b0 T __libc_csu_init
                 U __libc_start_main
0000000000000000 a __preinit_array_end
0000000000000000 a __preinit_array_start
0000000000401980 A _edata
0000000000401994 A _end
0000000000400494 T _fini
000000000040047c T _init
0000000000400220 T _start
000000000040024c t call_gmon_start
0000000000401980 b completed.6118
0000000000401788 W data_start
0000000000400270 t deregister_tm_clones
0000000000401988 b dtor_idx.6120
0000000000401994 A end
0000000000400350 t frame_dummy
0000000000401990 B g_my_num                   # our global g_my_num
0000000000400390 T main                       # the int main() function
00000000004002a0 t register_tm_clones

$ nm ok | c++filt            # c++filt "unmangles" identifiers...
00000000004017c8 d _DYNAMIC
0000000000401960 d _GLOBAL_OFFSET_TABLE_
0000000000400478 R _IO_stdin_used
                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
                 w _Jv_RegisterClasses
000000000040037c T f()
0000000000401798 D NS::ns_my_num
00000000004017a8 d __CTOR_END__
00000000004017a0 d __CTOR_LIST__
00000000004017b8 d __DTOR_END__
00000000004017b0 d __DTOR_LIST__
0000000000400540 r __FRAME_END__
00000000004017c0 d __JCR_END__
00000000004017c0 d __JCR_LIST__
00000000004017c8 d __TMC_END__
00000000004017c8 d __TMC_LIST__
0000000000401980 A __bss_start
0000000000401788 D __data_start
0000000000400440 t __do_global_ctors_aux
00000000004002e0 t __do_global_dtors_aux
0000000000401790 d __dso_handle
0000000000000000 a __fini_array_end
0000000000000000 a __fini_array_start
                 w __gmon_start__
0000000000000000 a __init_array_end
0000000000000000 a __init_array_start
00000000004003a0 T __libc_csu_fini
00000000004003b0 T __libc_csu_init
                 U __libc_start_main
0000000000000000 a __preinit_array_end
0000000000000000 a __preinit_array_start
0000000000401980 A _edata
0000000000401994 A _end
0000000000400494 T _fini
000000000040047c T _init
0000000000400220 T _start
000000000040024c t call_gmon_start
0000000000401980 b completed.6118
0000000000401788 W data_start
0000000000400270 t deregister_tm_clones
0000000000401988 b dtor_idx.6120
0000000000401994 A end
0000000000400350 t frame_dummy
0000000000401990 B g_my_num
0000000000400390 T main
00000000004002a0 t register_tm_clones

Notes:

笔记:

  • our functions f()and main()are type T(which stands for "TEXT" - used for read-only non-zero memory content whether it's actually text or other data or executable code),
  • g_my_numis Bbeing a global with implicitly zero-ed out memory, while
  • NS::ns_my_numis Das the executable has to explicitly provide the value 2to occupy that memory.
  • 我们的函数f()main()类型T(代表“文本”-用于只读非零内存内容,无论它实际上是文本还是其他数据或可执行代码),
  • g_my_numB一个具有隐式清零内存的全局变量,而
  • NS::ns_my_numD作为可执行具有明确提供的价值2占据内存。

The man/info-page for nmdocuments these things further....

用于nm进一步记录这些内容的手册/信息页面....

回答by Axel

The -g flag tells the compiler to generate debugging information. It has no impact on whether or not a core file will be generated. On most unix-like systems, that can be setup using the ulimit command.

-g 标志告诉编译器生成调试信息。它对是否生成核心文件没有影响。在大多数类 Unix 系统上,可以使用 ulimit 命令进行设置。

回答by Erik

The gcc -g flag tells gcc to generate and embed debug information. ulimit -cis used to enable core file generation. You can have either of these without the other.

gcc -g 标志告诉 gcc 生成和嵌入调试信息。ulimit -c用于启用核心文件生成。您可以拥有其中任何一个而没有另一个。

回答by JeremyP

-gadds debugging information (variable names, line numbers etc) to the executable file. It's part of what you need to do to be able to make sense of the core file.

-g向可执行文件添加调试信息(变量名、行号等)。这是您能够理解核心文件所需要做的一部分。

http://gcc.gnu.org/onlinedocs/gcc/Debugging-Options.html#Debugging-Options

http://gcc.gnu.org/onlinedocs/gcc/Debugging-Options.html#Debugging-Options

回答by Steven Wong

If you don't put -g flag, cannot call list in gdb to list what the source code looks like. it will show "No symbol table is loaded. Use the "file" command."

如果不放置 -g 标志,则无法在 gdb 中调用 list 来列出源代码的样子。它将显示“未加载符号表。使用“文件”命令。

Also if you type info func or info frame, info locals in gdb, without -g it will not show return datatype and its arguments, basically no translation of instruction to variable (mapping from symbol table).

此外,如果您在 gdb 中键入 info func 或 info frame, info locals,没有 -g 它不会显示返回数据类型及其参数,基本上不会将指令转换为变量(从符号表映射)。

回答by pepero

core dump is one of a process′s default actions, when this process receives the signals, e.g. in the standard signals "SIGQUIT", "SIGILL", "SIGABRT", "SIGFPE", "SIGSEGV". However, most shells suppress the creation of core file, simply because the core files tend to be large and it can take some time or a lot of time.

核心转储是进程的默认操作之一,当该进程接收到信号时,例如在标准信号“SIGQUIT”、“SIGILL”、“SIGABRT”、“SIGFPE”、“SIGSEGV”中。然而,大多数 shell 会抑制核心文件的创建,仅仅是因为核心文件往往很大并且可能需要一些时间或很多时间。

in order to enable the core generation, "ulimit" is the utility that you can use to set the shell or its children process′s file limit.

为了启用核心生成,“ulimit”是您可以用来设置 shell 或其子进程的文件限制的实用程序。

compiler flags "-g" or whatever only concern with compiler. logically speaking, it has nothing to do with core dump.

编译器标志“-g”或任何只与编译器有关的标志。从逻辑上讲,它与核心转储无关。

回答by vpit3833

core file is generated on Segmentation Fault or such exceptions. gdb source.cc coreis one way to look into the core file. Backtrace and investigating every frame is a start at looking into the core. -gadds debugging symbols in the binary.

core 文件是在 Segmentation Fault 或此类异常上生成的。 gdb source.cc core是查看核心文件的一种方法。回溯和调查每一帧是研究核心的开始。 -g在二进制文件中添加调试符号。