Библиотека сайта rus-linux.net
Малоизвестные полезные параметры компилятора GCC - часть 1
Оригинал: Uncommon but useful GCC command line options
Автор: Himanshu Arora
Дата публикации: 28 ноября 2016 г.
Перевод: А.Панин
Дата перевода: 7 февраля 2017 г.
Любые специфические инструменты позволяют использовать множество функций, но, как многие наверняка согласятся, не все эти функции необходимы большинству пользователей. Вообще говоря, в этом нет ничего плохого, ведь каждый пользователь решает с помощью таких инструментов свои задачи и обычно не использует их для выполнения работ в других областях. Однако, всегда полезно исследовать доступные инструменты, ведь вы никогда не сможете заранее сказать, какая из их возможностей в будущем окажется полезной и сохранит ваше драгоценное время.
Актуальный пример: компиляторы. Хороший компилятор любого языка программирования всегда поддерживает огромное количество параметров, но пользователи обычно знают и используют лишь их ограниченное количество. В частности, если вы разрабатываете код на языке C и используете Linux в качестве платформы для разработки программных продуктов, высока вероятность того, что вы используете компилятор GCC, который поддерживает огромное количество параметров командной строки.
Знаете ли вы о том, что вы можете сообщить GCC о необходимости сохранения результатов работы на каждом из этапов процесса компиляции кода? Знаете ли во том, что параметр -Wall
, предназначенный для генерации предупреждений, не позволяет генерировать их в некоторых специфических случаях? GCC поддерживает множество редко используемых параметров командной строки, которые могут оказаться весьма полезными в определенных ситуациях, например, в процессе отладки кода.
Исходя из всего вышесказанного, в рамках данной статьи будет рассматриваться несколько таких параметров с их подробными описаниями и понятными примерами использования.
Но перед тем, как перейти к рассмотрению параметров компилятора, следует упомянуть о том, что все примеры, команды и инструкции из данной статьи были протестированы в системе Ubuntu 16.04 LTS с компилятором GCC версии 5.4.0.
Сохранение промежуточных результатов на каждом из этапов процесса компиляции кода
Знаете ли вы о том, что в процесс компиляции вашего кода на языке C с помощью компилятора GCC может быть разделен на четыре этапа? Этими этапами являются предварительная обработка кода, компиляция, ассемблирование и связывание. В процессе выполнения каждого из этапов GCC генерирует временный файл, который предназначен для обработки на следующем этапе. Но ввиду того, что эти файлы являются временными, мы не видим их; мы просто выполняем команду компиляции и получаем в результате бинарный (исполняемый) файл, который мы можем самостоятельно запустить.
Но представьте, что вы осуществляете отладку кода и вам просто необходимо видеть его состояние, скажем, после этапа предварительной обработки. Что делать в этом случае? Ну, вам повезло, ведь компилятор GCC поддерживает параметр командной строки, который вы можете использовать в вашей стандартной команде компиляции для сохранения описанных временных файлов, обычно автоматически удаляемых компилятором. Мы говорим о параметре -save-temps
.
А это информация об этом параметре со
Сохранять "временные" промежуточные файлы на постоянной основе; эти файлы будут размещаться в текущей директории и иметь имена, соответствующие имени файла исходного кода. Таким образом, в случае компиляции файла исходного кода foo.c
с параметрами -c -save-temps
помимо файла foo.o
будут сгенерированы файлы foo.i
и foo.s
. Данный параметр позволяет сгенерировать файл foo.i
даже несмотря на то, что в текущее время компилятор по умолчанию использует встроенный препроцессор.
При использовании параметра -save-temps
совместно с параметром -x
содержимое файла исходного кода не будет заменяться на содержимое промежуточного файла с тем же расширением. Соответствующий промежуточный файл будет сохранен лишь в случае переименования файла исходного кода перед использованием параметра -save-temps
.
Ниже приведен пример команды, который позволяет понять принцип использования рассматриваемого параметра:
gcc -Wall -save-temps test.c -o test-exec
А это результат проверки факта генерации промежуточных файлов после исполнения данной команды:
Как несложно заметить при рассмотрении приведенного выше снимка экрана, файлы test.i
, test.s
и test.o
были успешно сгенерированы благодаря использованию параметра -save-temps
. Эти файлы были сгенерированы на этапах предварительной обработки, компиляции и связывания соответственно.
Подготовка кода к отладке и профилированию
Существует множество специализированных инструментов, позволяющих осуществлять отладку и профилирование вашего исходного кода. Например, инструмент
Давайте начнем с рассмотрения вопроса подготовки кода к отладке. Для того, чтобы успешно использовать отладчик GDB для отладки вашего кода вам придется скомпилировать этот код с использованием параметра -g
компилятора GCC. По сути, этот параметр сообщает GCC о том, что следует генерировать отладочную информацию, которая требуется отладчику GDB для корректной отладки вашей программы.
Если вы планируете использовать данный параметр командной строки, вам следует ознакомиться с его
GCC позволяет вам использовать параметр для генерации отладочной информации -g
совместно с параметром для указания механизма оптимизации -O
. При оптимизации кода могут наблюдаться неоднозначные явления: некоторые объявленные вами переменные могут просто не существовать; порядок исполнения инструкций может кратковременно неожиданно изменяться; некоторые инструкции могут не исполняться из-за того, что они возвращают неизменные результирующие значения или эти значения были уже получены; некоторые инструкции могут исполняться в других местах, так как они были вынесены из циклов.
Несмотря на все вышесказанное, отладка оптимизированного кода все же является возможной. Это обстоятельство позволяет использовать механизм оптимизации кода даже в программах, которые могут содержать ошибки.
Параметр -g
позволяет не только корректно использовать отладчик GDB, но и получать максимум информации от инструмента под названием memcheck из комплекта поставки Valgrind. Для тех, кто не знаком с данным инструментом, следует пояснить, что memcheck используется программистами главным образом для выявления утечек памяти (если таковые имеются) в своем коде. Вы можете узнать больше об этом инструменте из
Кроме того, вы должны использовать параметр командной строки компилятора -pg
для того, чтобы осуществлять профилирование вашего кода с помощью профилировщика GProf. Он позволяет компилятору GCC генерировать дополнительный код для передачи информации о профилировании, которая требуется для корректной работы GProf. На
Примечание: совместное использование параметров -g
и -pg
допустимо и также безопасно, как и совместное использование параметров -save-temps
и -x
, о котором было сказано выше.
Заключение
Если вы не являетесь экспертом в области работы с компилятором GCC, вы наверняка узнали кое-что новое из данной статьи. Самостоятельно испытайте описанные параметры компилятора в работе и оцените результаты их использования. В следующей статье серии мы обсудим еще несколько интересных и полезных параметров компилятора GCC.