А.В. Столяров, И.Г. Головин, И.А. Волкова - Операционная система Unix (1115132), страница 10
Текст из файла (страница 10)
Реультат макропроцессирования выдается на стандартный вывод. Эта опция может быть полезна, если ваши макроопределения повели себя не так, как вы ожидали, и хочетсяпонять, что на самом деле происходит.• -D позволяет с командной строки (т.е. без изменения исходныхфайлов) определить в программе некий макросимвол.
Это полезно, если в вашей программе используются директивы условной компиляции и требуется, не изменяя исходных файлов, быстро откомпилировать альтернативную версию программы. Например, -DDEBUG=2 имеет такой же эффект, какой дала бы директива #define DEBUG 2 в начале исходного файла.• -l позволяет подключить к программе библиотеку функций. Так,если в вашей программе используются математические функции (sin, exp и другие), необходимо при компиляции задатьключ -lmath; в некоторых вариантах ОС Unix (например, вSunOS/Solaris) при использовании сокетов вам понадобится такжеключ -lnsl.• -MM анализирует заданные исходные файлы и строит информациюоб их взаимозависимостях.
О том, как использовать полученнуюинформацию, рассказывается в §4.3.Итк, чтобы откомпилировать программу, написанную на языке C и целиком находящуюся в файле prog.c, следует дать командуgcc -g -Wall prog.c -o progПри этом результат компиляции будет помещен в файл prog в текущейдиректории.49Чтобы откомпилировать программу, состоящую из нескольких модулей mod1.c, mod2.c, mod3.c и главного файла prog.c, следует сначалаоткомпилировать все модули:$ gcc -g -Wall -c mod1.c$ gcc -g -Wall -c mod2.c$ gcc -g -Wall -c mod3.cи получить объектные файлы mod1.o, mod2.o, mod3.o.
После этого длякомпиляции основного файла и сборки готовой программы следует датькоманду$ gcc -g -Wall mod1.o mod2.o mod3.o prog.c -o prog4.2Отладчик gdbОтладчик gdb (Gnu DeBugger) позволяет отлаживать программу винтерактивном режиме, пользуясь интерфейсом командной строки, атакже анализировать причины “смерти” программы по созданному системой core-файлу.Учтите, что для нормальной работы отладчика необходимо, чтобывсе модули вашей программы были откомпилированы с ключем -ggdbили -g (см. §4.1).
В некоторых случаях нормальной работе отладчикаможет помешать включенный при компиляции режим оптимизации, такчто перед отладкой оптимизацию лучше отключить.4.2.1Пошаговое выполнение программыЧтобы запустить отладчик для программы, исполняемый файл которой называется prog, следует дать команду$ gdb progОтладчик сообщит свою версию и некоторую другую информацию, после чего выдаст приглашение своей командной строки, обычно выглядящее так: (gdb).Основные команды отладчика:• run осуществляет запуск программы в отладочном режиме.
Передзапуском целесообразно задать точки останова (см. ниже). Есливы затрудняетесь определить, где именно следует приостановитьвыполнение программы, поставьте точку останова на функциюmain().50• list показывает на экране несколько строк программы, предшествующих текущей и идущих непосредственно после текущей.• break позволяет задать точку приостановки выполнения программы (breakpoint). Точка останова может быть задана именем функции, номером строки в текущем файле, либо выражением <имяфайла>:<номер-строки>, например file1.c:73.• inspect позволяет просмотреть значение переменной (в том числеи заданной сложным выражением вроде *(a[i+1].p)).• backtrace или bt показывает текущее содержимое стека, что позволяет узнать последовательность вызовов функций, приведшуюк текущему состоянию программы.• frame позволяет сделать текущим один из фреймов, показанныхкомандой backtrace, что дает возможность исследовать значенияпеременных в этом фрейме и т.п.• step позволяет выполнить одну строку программы.
Если в строкесодержится вызов функции, текущей строкой станет первая строка этой функции (т.е. процесс трассировки зайдет внутрь функции).• next подобна команде step, с тем отличием, что вход в тела вызываемых функций не производится.• until <номер-строки> позволяет выполнять программу до техпор, пока текущей не окажется строка с указанным номером.• call позволяет выполнить вызов произвольной функции.• cont позволяет продолжить прерванное выполнение программы.• help позволит узнать подробнее об этих и других командах отладчика.• quit завершает работу отладчика (можно также воспользоватьсякомбинацией клавиш Ctrl-D).514.2.2Анализ причин аварийного завершения по core-файлуЧасто ошибки в программе приводят к ее аварийному завершению,при котором система создает так называемый core-файл.
При этом выдается сообщениеSegmentation fault (core dumped)Это означает, что в текущей директории аварийно завершенного процесса создан файл с именем core (или prog.core, где prog – имя вашейпрограммы), в который система записала содержимое сегмента данныхи стека программы на момент ее аварийного завершения.С помощью отладчика gdb можно проанализировать этот файл,узнав, в частности, при выполнении какой строки программы произошла авария, откуда и с какими параметрами была вызвана функция,содержащая эту строку, каковы были значения переменных на моментаварии и т.д.Чтобы запустить отладчик в режиме анализа core-файла, необходимо дать команду:gdb prog prog.coreгде prog – имя исполняемого файла вашей программы, а prog.core –имя созданного системой core-файла17 . Очень важно при этом, чтобыв качестве исполняемого файла выступал именно тот файл, при исполнении которого получен core-файл. Так, если уже после полученияcore-файла вы перекомпилируете свою программу, анализ core-файла,скорее всего, приведет к ошибочным результатам.Сразу после запуска отладчика в режиме анализа core-файла рекомендуется дать команду backtrace (или просто bt).4.2.3Анализ причин зацикливанияЕсли ваш процесс зациклился, не торопитесь его убивать.
С помощью отладчика можно понять, какой фрагмент кода выполняется в настоящий момент, и проанализировать причины зацикливания. Для этого нужно присоединить отладчик к существующему процессу. Определите номер процесса с помощью команды ps. Допустим, имя исполняемого файла вашей программы – prog, и она выполняется как процессномер 12345. Тогда команда запуска отладчика должна выглядеть так:17 Подобное имя core-файла характерно для ОС FreeBSD.
В ОС Linux файл, скореевсего, будет называться просто core.52gdb prog 12345При подключении отладчика выполнение программы будет приостановлено, однако вы сможете при необходимости продолжить его командойcont. В случае повторного зацикливания можно приказать отладчикувновь приостановить выполнение нажатием комбинации Ctrl-C.4.3Утилита makeПри сборке ваших программ могут оказаться полезны возможности,предоставляемые утилитой make. Кратко говоря, эта утилита позволяет автоматически строить одни файлы на основании других (например,исполняемые файлы на основании исходных текстов программы) в соответствии с заданными правилами.
При этом make отслеживает датыпоследней модификации файлов и производит перестроение только техцелевых файлов, для которых исходные файлы претерпели изменения.Существует несколько различных версий утилиты make.Изложенное в данном параграфе соответствует варианту GnuMake; именно этот вариант используется в большинстве дистрибутивов Linux.
При работе с ОС FreeBSD для вызова GnuMake необходимо использовать команду gmake вместо make. Вслучае, если в системе такой команды нет, обратитесь к системномуадминистратору с просьбой её установить.Правила для утилиты make задаются в файле Makefile, которыйутилита ищет в текущей директории.4.3.1Простейший MakefileДопустим, ваша программа состоит из главного модуля main.c,содержащего функцию main(), а также из дополнительных модулейmod1.c и mod2.c, имеющих заголовочные файлы mod1.h и mod2.h. Соответственно, для сборки исполняемого файла (назовем его prog) необходимо дать следующие команды:$ gcc -g -Wall -c mod1.c -o mod1.o$ gcc -g -Wall -c mod2.c -o mod2.o$ gcc -g -Wall main.c mod1.o mod2.o -o progПервые две команды даются для компиляции дополнительных модулей.
Полученные в результате файлы mod1.o и mod2.o используются втретьей команде для сборки исполняемого файла.53Допустим, мы уже произвели компиляцию программы, после чеговнесли изменения в файл mod1.c и хотим получить исполняемый файл сучетом внесенных изменений. При этом нам надо будет дать только двекоманды (первую и третью), поскольку перекомпиляции модуля mod2не требуется.Чтобы подобные ситуации отслеживались автоматически, мы можемиспользовать утилиту make.
Для этого напишем следующий Makefile:mod1.o: mod1.c mod1.hgcc -g -Wall -c mod1.c -o mod1.omod2.o: mod2.c mod2.hgcc -g -Wall -c mod2.c -o mod2.oprog: main.c mod1.o mod2.ogcc -g -Wall main.c mod1.o mod2.o -o progПоясним, что файл состоит из так называемых целей (в нашем случае таких целей три - mod1.o, mod2.o и prog). Описание каждой целисостоит из заголовка и списка команд. Заголовок цели – это одна строка, начинающаяся всегда с первой позиции (т.е. перед ней не допускаются пробелы и т.п.).
В начале строки пишется имя цели (обычно этопросто имя файла, который необходимо построить). Оставшаяся частьзаголовка отделяется от имени цели двоеточием. После двоеточия перечисляется, от каких файлов (или, в более общем случае, от каких целей)зависит построение файла. В данном случае мы указали, что модули зависят от их исходных текстов и заголовочных файлов, а исполняемыйфайл – от основного исходного файла и от двух объектных файлов.После строки заголовка идет список команд (в нашем случае всетри списка имеют по одной команде). Строка команды всегда начинается с символа табуляции, причем замена табуляции пробеламинедопустима и ведет к ошибке. Утилита make считает признаком концасписка команд первую строку, начинающуюся с символа, отличного оттабуляции.Имея в текущей директории вышеописанный Makefile, мы можемдля сборки нашей программы дать команду make prog.4.3.2ПеременныеВ предыдущем параграфе описан Makefile, в котором можно обнаружить несколько повторяющихся фрагментов.