gcc -g: что будет - PullRequest
       11

gcc -g: что будет

40 голосов
/ 03 марта 2011

Этот вопрос был задан мне в интервью.

они спросили меня, как создать файл дампа ядра, с помощью которого я могу отлаживать. затем я сказал, что с -g флагом в gcc мы можем сделать это.

затем они спросили меня, что именно этот флаг -g делает с компилятором.

Я сказал (возможно, неправильный ответ), что он откроет все символы в основном файле, которые можно использовать для отладки.

Может кто-нибудь сказать мне, что именно он делает?

Ответы [ 7 ]

48 голосов
/ 03 марта 2011

Это вроде правильно, но не полностью. -g запрашивает, чтобы компилятор и компоновщик генерировали и сохраняли информацию об отладке / символах на уровне исходного кода в самом исполняемом файле.

Если ...

  • в дальнейшем происходит сбой программы и создается файл ядра (что указывает на некоторую проблему в реальном коде), или
  • преднамеренная команда ОС принудительно привела его к ядру (например, kill -SIGQUIT pid ) или
  • программа вызывает функцию, которая создает дамп ядра (например, abort)

... - ни один из которых на самом деле не вызван использованием -g - тогда отладчик будет знать, как прочитать эту символьную информацию "-g" из исполняемого файла и сопоставить ее с ядром. Это означает, что вы можете видеть правильные имена переменных и функций в ваших стековых фреймах, получать номера строк и видеть источник при переходе в исполняемый файл.

Эта отладочная информация полезна при отладке - начинаете ли вы с ядра или только с исполняемого файла. Это даже помогает получить лучший результат от таких команд, как pstack.

Обратите внимание, что в вашей среде могут быть другие настройки для управления генерацией ядер (они могут быть большими, и нет общего способа узнать, можно ли / когда их удалить, поэтому они не всегда нужны). Например, в оболочках UNIX / LINUX это часто ulimit -c.

Вам также может быть интересно прочитать о DWARF Википедии - широко используемом формате отладочной информации для кодирования встроенной информации отладки / символов в исполняемых / библиотечных объектах (например, в UNIX и Linux).

ОБНОВЛЕНИЕ по запросу Виктора в комментариях ...

Информация о символах перечисляет идентификаторы из исходного кода (обычно только после любого искажения имени необходимых), адреса / смещения (виртуальной) памяти, при которых они будут загружены в память процесса, тип (например, данные против кода). Например ...

$ 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 (что означает «ТЕКСТ» - используется для ненулевого содержимого памяти, доступного только для чтения, будь то текст, другие данные или исполняемый код), * ​​1057 *
  • g_my_num - это B глобал с неявно обнуленной памятью, в то время как
  • NS::ns_my_num равно D, поскольку исполняемый файл должен явно предоставить значение 2, чтобы занять эту память.

Страница man / info для nm документирует эти вещи дальше ...

9 голосов
/ 03 марта 2011

Флаг -g указывает компилятору генерировать отладочную информацию.Это не влияет на то, будет ли генерироваться основной файл.На большинстве unix-подобных систем это можно настроить с помощью команды ulimit.

5 голосов
/ 03 марта 2011

Флаг gcc -g указывает gcc генерировать и вставлять отладочную информацию. ulimit -c используется для включения генерации файла ядра. Вы можете иметь один из них без другого.

3 голосов
/ 03 марта 2011

-g добавляет отладочную информацию (имена переменных, номера строк и т. Д.) В исполняемый файл.Это часть того, что вам нужно сделать, чтобы понять основной файл.

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

1 голос
/ 23 июля 2017

Если вы не укажете флаг -g, вы не сможете вызвать список в gdb, чтобы увидеть, как выглядит исходный код.он покажет «Таблица символов не загружена. Используйте команду« file ».»

Также, если вы введете info func или info frame, info localals в gdb, без -g он не покажет тип возвращаемого данных и егоаргументы, в основном нет перевода инструкции в переменную (отображение из таблицы символов).

1 голос
/ 24 апреля 2013

основной дамп является одним из действий процесса по умолчанию, когда этот процесс получает сигналы, например, в стандартных сигналах «SIGQUIT», «SIGILL», «SIGABRT», «SIGFPE», «SIGSEGV».Однако большинство оболочек подавляют создание файла ядра просто потому, что файлы ядра имеют тенденцию быть большими, и это может занять некоторое время или много времени.

, чтобы включить генерацию ядра, «ulimit» - это утилита, которую вы можете использовать для установки ограничения файла оболочки или дочернего процесса.

флаги компилятора "-g" или все, что касается только компилятора.логически говоря, это не имеет ничего общего с дампом ядра.

1 голос
/ 03 марта 2011

основной файл создается при ошибке сегментации или подобных исключениях.gdb source.cc core - это один из способов заглянуть в основной файл.Отслеживание и изучение каждого кадра - это начало изучения ядра.-g добавляет символы отладки в двоичный файл.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...