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

这个问题在接受采访时问我。

他们问我如何生成一个核心转储文件,我可以调试。
然后我说,用-g标志在gcc我们可以做到。

那么他们问我-g标志对编译器究竟做了什么。

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

任何人都可以告诉我它究竟做了什么?

最佳答案
这是正确的,但不完全。 -g请求编译器和链接器在可执行文件本身中生成和保留符号信息。

如果程序碰巧后来崩溃,并产生一个核心文件(这表明在实际代码中的一些问题),或一个故意的操作系统命令强制它的核心(例如杀死-SIGQUIT pid),或程序调用一个函数转储核心例如abort) – 其中没有一个实际上是由使用-g引起的,那么调试器将知道如何从可执行文件读取“-g”符号信息,并与核心交叉引用它。这意味着您可以在堆栈框架中查看变量和函数的正确名称,获取行号并在可执行文件中查看源代码。

该符号信息在调试时非常有用 – 不管你是从核心开始,还是仅仅是可执行文件。它甚至有助于从命令如pstack产生更好的输出。

在评论中更新Victor的请求…

符号信息列出来自源代码的标识符(通常仅在需要任何name mangling之后),它们将被加载到过程存储器中的(虚拟)存储器地址/偏移,类型(例如数据对代码)。例如…

$ 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

注意,我们的函数f()和main()是类型T,g_my_num是B是一个全局的隐式零出内存,而NS :: ns_my_num是D,因为可执行文件必须显式提供值2占用那个内存。 nm的人/信息页将记录这些事情….

转载注明原文:c++ gcc -g:会发生什么 - 代码日志