Использование набора компиляторов gcc и отладчика gdb
Лабораторная работа №1
Цель работы
Ознакомиться с набором компиляторов gcc и отладчиком gdb; написать, скомпилировать с помощью gcc (с различными опциями сборки) программу на языке С; отладить программу в gdb.
Содержание работы
- Ознакомиться с назначением, возможностями и особенностями работы с набором компиляторов gcc;
- Ознакомиться с назначением, возможностями и режимами работы отладчика gdb;
- Составить программу на языке С, реализующую требуемые действия.
- Скомпилировать, отладить и протестировать составленную программу, используя gcc и gdb;
- Ответить на контрольные вопросы.
Методические указания к лабораторной работе
Особенностью UNIX является то, что это была первая ОС, написанная на языке, отличном от ассемблера. Для целей написания UNIX и системного ПО для нее, параллельно велись работы по созданию эффективного языка высокого уровня, которые закончились созданием языка C (Си). В 1973 году ОС UNIX была переписана окончательно на языке С. В результате появилась ОС, 90% кода которой было написано на языке высокого уровня, языке, не зависящем от архитектуры машины и системы команд, а 10% было написано на ассемблере, в эти 10% входят наиболее критичные к реализации по времени части ядра ОС.
Язык С сконструирован таким образом, что позволяет писать эффективные программы и транслировать их в эффективный машинный код.
В UNIX-системах для компиляции программ традиционно используется набор компиляторов gcc (GNU compiler collection) , который включает компиляторы С и С++. В этом же наборе имеется еще несколько компиляторов, в том числе и ассемблер.
Для компиляции программ на С предназначен компилятор cc, а для программ на языке С++ — компилятор g++. Синтаксис вызова у них одинаковый:
gcc <options> infile <-o outfile> //cc и g++ вызываются аналогично
Где:
- infile – имя файла с исходным текстом;
- options – список необязательных параметров;
- outfile (с параметром -o) – выходной файл. Если параметр не указан, то будет создан исполняемый файл с именем a.out.
Компиляторы из набора gcc имеют много различных опциональных параметров, что позволяет очень тонко настраивать процесс компиляции. Список общих параметров доступен при вызове программы с ключом --help (-v --help – для отображения всех, а их очень много, параметров). Подробную информацию о их назначении можно получить в man gcc или в Руководстве пользователя gcc (часть 1, часть 2). Здесь же перечислим только некоторые параметры:
- -с – не ассемблировать, но создавать объектный файл (.о);
- -S – не ассемблировать, но создавать файл с ассемблерным кодом (.s);
- -I <path> — включить дополнительные файлы;
- -L <path> — включить дополнительные библиотеки;
- -g (или -ggdb) – включить в исполняемый файл отладочную информацию (при указании -ggdb будет представлена расширенная отладочная информация).
Для отладки программ используется отладчик gdb. Синтаксис его вызова следующий:
gdb <executable_file>
Отладчик gdb – интерактивный, поэтому его можно запускать без параметров, а задавать их прямо из него. Если указано имя исполнимого файла (executable_file), то он будет сразу же загружен в отладчик.
Приведем несколько интерактивных команд gdb:
- help – вывести справку о gdb;
- b <line_num> — установить точку останова в строке line_num;
- run – запустить программу на исполнение;
- start – начать пошаговое выполнение;
- next – выполнить следующую строку с обходом функций;
- step – выполнить следующую строку со входом в функцию;
- kill – прекратить выполнение отлаживаемой программы;
- print <var_name> — показать значение переменной var_name;
- q – выход из отладчика.
Подробнее ознакомиться с использованием gdb можно на страницах руководств, например, этого.
Задания к работе (общий вариант)
- Написать исходный код программы, приведенной в листинге №1, ознакомиться с описанием (руководство man, см. раздел 3 «Library functions» и раздел 2 «Linux Programmer’s Manual») используемых в программе системных функций (open, read, write, printf, close);
- Cкомпилировать написанную программу, включив в объектный модуль отладочную информацию;
- Запустить скомпилированную программу;
- Перекомпилировать программу без ассемблирования, ознакомиться с полученным ассемблерным кодом
- Переписать программу, исключив процедуру запроса имени файла, скомпилировать полученную программу с включением отладочной информации;
- Перекомпилировать новую программу без ассемблирования, сравнить ассемблерный код полученный при компиляции с кодом, полученным в п. 4. Какой из них компактней и почему (ответ привести в списке ответов на контрольные вопросы)?;
Листинг №1
/*----------------------------------------------------------------------------- Программа sample1.c к ЛР №1, которая выполняет запись и чтение файла. Программа принимает в качестве параметра командной строки имя рабочего файла. Если файл не существует, он будет создан. -------------------------------------------------------------------------------*/ #include <stdio.h> #include <sys/types.h> #include <fcntl.h> #include <errno.h> extern int errno; // код ошибки, если она возникнет int fd; //дескриптор файла, имя задается из коммандной строки //запись в файл 10 чисел int writeToFile() { static int j = 1; if (j > 10) return 0; write(fd, &j, sizeof(int)); printf("Write %i to file (fd %i)\t", j++, fd); return 1; } //чтение из файла void readFromFile() { int i = 0; lseek(fd,-sizeof(int), 1); read(fd,&i, sizeof(int)); printf("Read %i from file (fd %i)\n", i, fd); } int main(int argc, char *argv[]) { // Раскомментируйте следующую строку для просмотра // списка аргументов командной строки //printf("Param count: %i \nParam list : %s, %s \n\n", argc, argv[0],argv[1]); // проверить параметры командной строки if (argc != 2) { puts("Usage: sample1 <outfile>\n"); return -1; } // проверить, не возникло ли ошибки при открытии файла if ((fd = open(argv[1], O_CREAT | O_RDWR))==-1) { perror("ERROR: "); return -1; } // цикл записи/чтения файла while (writeToFile()) readFromFile(); close(fd); return 0; }
Контрольные вопросы
- Какое значение принимает первый параметр функции main?
- Отличаются ли результаты выполнения программы при указании нового файла и при выборе существующего?
- С чем связана ошибка в программе из примера №1, возникающая (если это так) при обращении к имеющемуся файлу?
- Как можно устранить ошибку (если она возникает), описанную в п. 3 программными средствами (см. описание функции open) и средствами операционной системы?
CC-BY-CA Анатольев А.Г., 31.01.2012