gcc -g :what will happen

后端 未结 7 1038
隐瞒了意图╮
隐瞒了意图╮ 2021-01-30 00:51

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 -g flag in

相关标签:
7条回答
  • 2021-01-30 01:19

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

    0 讨论(0)
  • 2021-01-30 01:21

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

    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 -SIGQUIT pid), or
    • the program calls a function that dumps core (e.g. 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.

    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.

    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.

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

    UPDATE per Victor's request in comments...

    Symbol information lists identifiers from the source code (usually only after any name mangling needed), 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_num is B being a global with implicitly zero-ed out memory, while
    • NS::ns_my_num is D as the executable has to explicitly provide the value 2 to occupy that memory.

    The man/info-page for nm documents these things further....

    0 讨论(0)
  • 2021-01-30 01:33

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

    0 讨论(0)
  • 2021-01-30 01:33

    -g adds 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.

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

    0 讨论(0)
  • 2021-01-30 01:44

    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.

    0 讨论(0)
  • 2021-01-30 01:46

    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."

    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).

    0 讨论(0)
提交回复
热议问题