gcc -g:会发生什么

Vij*_*jay 41 c c++ gcc gdb

我在接受采访时问了这个问题.

他们问我如何生成我可以调试的核心转储文件.然后我说用-g旗帜gcc我们可以做到.

然后他们问我该-g标志对编译器的确切作用.

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

任何人都可以告诉我它到底是做什么的?

Ton*_*roy 50

这是正确的,但不完整. -g请求编译器和链接器在可执行文件本身中生成并保留源级调试/符号信息.

如果 ...

  • 程序碰巧崩溃并生成一个核心文件(这表明实际代码中存在一些问题),或者
  • 故意操作系统命令强制它进行核心(例如kill -SIGQUIT pid)或
  • 程序调用转储核心的函数(例如abort)

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

调试时,调试信息非常有用 - 无论是以核心还是仅从可执行文件开始.它甚至可以帮助从命令中产生更好的输出pstack.

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

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

根据Victor的评论请求更新......

符号信息列出源代码中的标识符(通常仅在需要任何名称修改之后),它们将被加载到进程存储器中的(虚拟)存储器地址/偏移量,类型(例如数据与代码).例如...

$ 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
Run Code Online (Sandbox Code Playgroud)

笔记:

  • 我们的函数f()main()类型T(代表"TEXT" - 用于只读非零内存内容,无论它实际上是文本还是其他数据或可执行代码),
  • g_my_numB一个具有隐式零排除内存的全局,而
  • NS::ns_my_numD作为可执行具有明确提供的价值2占据内存.

文件的人/信息页面nm这些东西进一步....

  • 注意:`strip`实用程序执行反向操作,即它需要一个带有调试符号的库并将其剥离. (4认同)

Axe*_*xel 10

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


Eri*_*rik 5

gcc -g标志告诉gcc生成并嵌入调试信息。ulimit -c用于启用核心文件生成。您可以同时拥有其中一个。