这个问题是在一次面试中被问到的。
他们问我如何生成一个核心转储文件,我可以用它进行调试。然后我说,在gcc中使用-g标志可以做到这一点。
然后他们问我-g标志到底对编译器做了什么。
我说(可能是错误的回答),它将打开核心文件中可用于调试的所有符号。
有人能告诉我它到底是做什么的吗?
发布于 2011-03-03 18:08:04
这是对的,但并不完整。-g要求编译器和链接器在可执行文件本身中生成并保留源代码级别的调试/符号信息。
如果...
kill -SIGQUIT pid),或者abort)...-所有这些实际上都不是由使用-g引起的-那么调试器就会知道如何从可执行文件中读取"-g“符号信息,并与内核交叉引用它.这意味着您可以在堆栈框架中看到变量和函数的正确名称,获得行号,并在可执行文件中查看源代码。
无论您是从核心启动还是仅从可执行文件启动,这些调试信息在调试时都很有用。它甚至有助于从pstack等命令生成更好的输出。
请注意,您的环境可能有其他设置来控制是否生成内核(它们可能很大,并且没有一般方法来知道是否/何时可以删除它们,因此它们并不总是需要的)。例如,在UNIX/LINUX上,它通常是ulimit -c。
您可能还会对DWARF Wikipedia感兴趣-这是一种常用的调试信息格式,用于编码可执行文件/库对象中的嵌入式调试/符号信息(例如,在UNIX和Linux上)。
根据维克多的请求在评论中更新...
符号信息列出了来自源代码的标识符(通常仅在需要任何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类型(代表“B”-用于只读非零内存内容,无论它实际上是文本、其他数据还是可执行代码),while
NS::ns_my_num是D,因为可执行文件必须显式提供值2才能占用该内存。man/info-page for nm对这些内容做了进一步的记录...
发布于 2011-03-03 18:07:41
-g标志告诉编译器生成调试信息。它对是否生成核心文件没有影响。在大多数类unix系统上,可以使用ulimit命令进行设置。
发布于 2011-03-03 18:08:50
gcc -g标志告诉gcc生成并嵌入调试信息。ulimit -c用于启用核心文件生成。你可以选择这两个中的任何一个而不是另一个。
https://stackoverflow.com/questions/5179202
复制相似问题