Учебно-методические материалы для студентов кафедры АСОИУ

Использование набора компиляторов gcc и отладчика gdb

Лабораторная работа №1

Цель работы

Ознакомиться с набором компиляторов gcc и отладчиком gdb; написать, скомпилировать с помощью gcc (с различными опциями сборки) программу на языке С; отладить программу в gdb.

Содержание работы

  1. Ознакомиться с назначением, возможностями и особенностями работы с набором компиляторов gcc;
  2. Ознакомиться с назначением, возможностями и режимами работы отладчика gdb;
  3. Составить программу на языке С, реализующую требуемые действия.
  4. Скомпилировать, отладить и протестировать составленную программу, используя gcc и gdb;
  5. Ответить на контрольные вопросы.

Методические указания к лабораторной работе

Особенностью UNIX является то, что это была первая ОС, написанная на языке, отличном от ассемблера. Для целей написания UNIX и системного ПО для нее, параллельно велись работы по созданию эффективного языка высокого уровня, которые закончились созданием языка C (Си). В 1973 году ОС UNIX была переписана окончательно на языке С. В результате появилась ОС, 90% кода которой было написано на языке высокого уровня, языке, не зависящем от архитектуры машины и системы команд, а 10% было написано на ассемблере, в эти 10% входят наиболее критичные к реализации по времени части ядра ОС.

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

В UNIX-системах для компиляции программ традиционно используется набор компиляторов gcc (GNU compiler collection) , который включает компиляторы С и С++. В этом же наборе имеется еще несколько компиляторов, в том числе и ассемблер.

Для компиляции программ на С предназначен компилятор cc, а для программ на языке С++ — компилятор g++. Синтаксис вызова у них одинаковый:

gcc <options> infile <-o outfile> //cc и g++ вызываются аналогично

Где:

  1. infile – имя файла с исходным текстом;
  2. options – список необязательных параметров;
  3. outfile (с параметром -o) – выходной файл. Если параметр не указан, то будет создан исполняемый файл с именем a.out.

Компиляторы из набора gcc имеют много различных опциональных параметров, что позволяет очень тонко настраивать процесс компиляции. Список общих параметров доступен при вызове программы с ключом --help (-v --help – для отображения всех, а их очень много, параметров). Подробную информацию о их назначении можно получить в man gcc или в Руководстве пользователя gcc (часть 1, часть 2). Здесь же перечислим только некоторые параметры:

Для отладки программ используется отладчик gdb. Синтаксис его вызова следующий:

gdb <executable_file>

Отладчик gdb – интерактивный, поэтому его можно запускать без параметров, а задавать их прямо из него. Если указано имя исполнимого файла (executable_file), то он будет сразу же загружен в отладчик.

Приведем несколько интерактивных команд gdb:

Подробнее ознакомиться с использованием gdb можно на страницах руководств, например, этого.

Задания к работе (общий вариант)

  1. Написать исходный код программы, приведенной в листинге №1, ознакомиться с описанием (руководство man, см. раздел 3 «Library functions» и раздел 2 «Linux Programmer’s Manual») используемых в программе системных функций (open, read, write, printf, close);
  2. Cкомпилировать написанную программу, включив в объектный модуль отладочную информацию;
  3. Запустить скомпилированную программу;
  4. Перекомпилировать программу без ассемблирования, ознакомиться с полученным ассемблерным кодом
  5. Переписать программу, исключив процедуру запроса имени файла, скомпилировать полученную программу с включением отладочной информации;
  6. Перекомпилировать новую программу без ассемблирования, сравнить ассемблерный код полученный при компиляции с кодом, полученным в п. 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;
}

Контрольные вопросы

  1. Какое значение принимает первый параметр функции main?
  2. Отличаются ли результаты выполнения программы при указании нового файла и при выборе существующего?
  3. С чем связана ошибка в программе из примера №1, возникающая (если это так) при обращении к имеющемуся файлу?
  4. Как можно устранить ошибку (если она возникает), описанную в п. 3 программными средствами (см. описание функции open) и средствами операционной системы?

CC-BY-CA Анатольев А.Г., 31.01.2012