Как параметр отладки -g изменяет двоичный исполняемый файл?

При написании кода C / C++ для отладки двоичного исполняемого файла необходимо включить параметр отладки в компиляторе / компоновщике. В случае GCC опция -g. Когда включена опция отладки, как это влияет на двоичный исполняемый файл? Какие дополнительные данные хранятся в файле, что позволяет отладчику работать в таком режиме?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
75
0
47 382
7
Перейти к ответу Данный вопрос помечен как решенный

Ответы 7

Ответ принят как подходящий

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

  • имена символов
  • информация о типе символов
  • файлы и номера строк, откуда взяты символы

Отладчики используют эту информацию для вывода значимых имен символов и для связывания инструкций с определенными строками в источнике.

Для некоторых компиляторов указание -g отключит определенные оптимизации. Например, icc устанавливает уровень оптимизации по умолчанию на -O0 с помощью -g, если вы явно не указали -O [123]. Кроме того, даже если вы укажете -O [123], оптимизации, предотвращающие трассировку стека, все равно будут отключены (например, удаление указателей фреймов из фреймов стека. Это лишь незначительно влияет на производительность).

В некоторых компиляторах -g отключит оптимизацию, которая может запутать происхождение символов (переупорядочение инструкций, развертывание цикла, встраивание и т. д.). Если вы хотите отладить с оптимизацией, вы можете использовать -g3 с gcc, чтобы обойти некоторые из этих проблем. Будет добавлена ​​дополнительная отладочная информация о макросах, расширениях и функциях, которые могли быть встроены. Это может позволить отладчикам и средствам повышения производительности сопоставлять оптимизированный код с исходным исходным кодом, но это лучшее усилие. Некоторые оптимизации действительно искажают код.

Для получения дополнительной информации взгляните на DWARF, формат отладки, изначально разработанный для использования с ELF (двоичный формат для Linux и других ОС).

Чтобы добавить к этому, это также может замедлить исполняемый файл. Я тестировал некоторый код OpenMP с компилятором Sun Studio, и с отладочной информацией код работал намного медленнее. Просто нужно иметь в виду.

Mike 18.09.2008 07:00

Если флаг -g в компиляторе Sun не отключает некоторые оптимизации, отладочная информация НЕ должна замедлять ваш код.

Todd Gamblin 18.09.2008 07:02

Это код OpenMP, и он действительно замедлял его. Я играл с фракталами и работал над расширениями компилятора OpenMP. Код в одном потоке работал медленнее, чем код без OpenMP в одном потоке. Отключил отладку и скорость выровняла.

Mike 18.09.2008 07:16

Отметил. Это действительно интересно. Может быть, он добавляет туда лишний материал, чтобы сообщить отладчику о параллельных регионах ... Здесь говорится (docs.sun.com/source/819-3683/OpenMP.html), что вы можете получить отображение основного потока обратно в источник, но не на подчиненные устройства, что тоже кажется странным.

Todd Gamblin 18.09.2008 07:29

Я думаю, что это так, конечно, не влияет на GCC, конечно, меня удивило, когда однопоточный код изменился с 11 секунд до 22.: / При отключенной отладке и 4 потоках (у меня Q6600) он упал примерно до 3 секунд .

Mike 18.09.2008 07:36

gcc4 на самом деле поддерживает OpenMP, поэтому, возможно, вы столкнетесь с подобными проблемами. Я слышал, что выступление не так уж и хорошо для начала.

Todd Gamblin 18.09.2008 07:41

Просто из любопытства, предоставили ли вы дополнительные параметры оптимизации при компиляции с помощью -g (например, -g -O3) или вы просто добавили -g без явного указания -O [123]? Первый может сбросить вас до -O0, по крайней мере, на icc.

Todd Gamblin 18.09.2008 07:43

У меня была настройка проекта на максимальную оптимизацию (с отладкой), SSE, MMX и т. д., Когда я вернусь домой, я опубликую точные параметры, возможно, я что-то пропустил.

Mike 18.09.2008 07:54

Хорошо, используя - #, чтобы указать, что -fast расширяется до: cc -xopenmp -fast - # Расширяется до: -D__MATHERR_ERRNO_DONTCARE -fns -nofstore -fsimple = 2 -fsingle -xalias_level = basic -xarch = ssse3 -xbuiltin =% all -xcache = 32/64/8: 4096/64/16 -xchip = core2 -xdepend -xlibmil -xlibmopt -xO5 -xopenmp -xregs = frameptr

Mike 20.09.2008 02:57

Флаг -g также включен, комментарии просто не дают мне места для публикации полной строки. :) Версия отладки: в реальном времени: 6.060 с, время пользователя: 22.815 с, версия выпуска: 3.774 с, время пользователя: 13.902 с (оба используют 4 потока)

Mike 20.09.2008 03:06

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

Есть некоторое совпадение с этим вопрос, которое покрывает проблему с другой стороны.

Просто ради интереса, вы можете взломать hexeditor и взглянуть на исполняемый файл, созданный с -g, а другой - без него. Вы можете видеть символы и то, что добавлено. Может поменять и сборку (-S), но я не уверен.

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

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

В дополнение к отладочной и символьной информации
Google DWARF (шутка разработчиков об ELF)

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

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

Дополнительную информацию см. В документации к компилятору:
Но пример для DevStudio:

  • 0xCDCDCDCD Allocated in heap, but not initialized
  • 0xDDDDDDDD Released heap memory.
  • 0xFDFDFDFD "NoMansLand" fences automatically placed at boundary of heap memory. Should never be overwritten. If you do overwrite one, you're probably walking off the end of an array.
  • 0xCCCCCCCC Allocated on stack, but not initialized

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

Другие вопросы по теме