Наши партнеры

UnixForum





Библиотека сайта 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.

А это информация об этом параметре со страницы руководства компилятора GCC:

Сохранять "временные" промежуточные файлы на постоянной основе; эти файлы будут размещаться в текущей директории и иметь имена, соответствующие имени файла исходного кода. Таким образом, в случае компиляции файла исходного кода 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 используется для отладки кода, а инструмент GProf является популярным профилировщиком. Но знаете ли вы о том, что существуют специфические параметры командной строки, которые позволяют компилятору GCC подготавливать ваш код к отладке и профилированию?

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

Если вы планируете использовать данный параметр командной строки, вам следует ознакомиться с его описанием на странице руководства компилятора GCC; это описание является подтверждением того, что в некоторых случаях данный параметр является просто необходимым:

GCC позволяет вам использовать параметр для генерации отладочной информации -g совместно с параметром для указания механизма оптимизации -O. При оптимизации кода могут наблюдаться неоднозначные явления: некоторые объявленные вами переменные могут просто не существовать; порядок исполнения инструкций может кратковременно неожиданно изменяться; некоторые инструкции могут не исполняться из-за того, что они возвращают неизменные результирующие значения или эти значения были уже получены; некоторые инструкции могут исполняться в других местах, так как они были вынесены из циклов.

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

Параметр -g позволяет не только корректно использовать отладчик GDB, но и получать максимум информации от инструмента под названием memcheck из комплекта поставки Valgrind. Для тех, кто не знаком с данным инструментом, следует пояснить, что memcheck используется программистами главным образом для выявления утечек памяти (если таковые имеются) в своем коде. Вы можете узнать больше об этом инструменте из данного руководства.

Кроме того, вы должны использовать параметр командной строки компилятора -pg для того, чтобы осуществлять профилирование вашего кода с помощью профилировщика GProf. Он позволяет компилятору GCC генерировать дополнительный код для передачи информации о профилировании, которая требуется для корректной работы GProf. На странице руководства компилятора GCC несложно обнаружить следующее описание данного параметра: "Вы должны использовать этот параметр при компиляции файлов исходного кода, информация о скорости исполнения инструкций из которых вас интересует, а также при связывании кода". Для ознакомления с особенностями процесса профилирования кода с помощью инструмента GProf вы можете обратиться к отдельной статье на нашем сайте.

Примечание: совместное использование параметров -g и -pg допустимо и также безопасно, как и совместное использование параметров -save-temps и -x, о котором было сказано выше.

Заключение

Если вы не являетесь экспертом в области работы с компилятором GCC, вы наверняка узнали кое-что новое из данной статьи. Самостоятельно испытайте описанные параметры компилятора в работе и оцените результаты их использования. В следующей статье серии мы обсудим еще несколько интересных и полезных параметров компилятора GCC.