Нейл Мэтью - Основы программирования в Linux
- Название:Основы программирования в Linux
- Автор:
- Жанр:
- Издательство:«БХВ-Петербург»
- Год:2009
- Город:Санкт-Петербург
- ISBN:978-5-9775-0289-4
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Нейл Мэтью - Основы программирования в Linux краткое содержание
В четвертом издании популярного руководства даны основы программирования в операционной системе Linux. Рассмотрены: использование библиотек C/C++ и стандартных средств разработки, организация системных вызовов, файловый ввод/вывод, взаимодействие процессов, программирование средствами командной оболочки, создание графических пользовательских интерфейсов с помощью инструментальных средств GTK+ или Qt, применение сокетов и др. Описана компиляция программ, их компоновка c библиотеками и работа с терминальным вводом/выводом. Даны приемы написания приложений в средах GNOME® и KDE®, хранения данных с использованием СУБД MySQL® и отладки программ. Книга хорошо структурирована, что делает обучение легким и быстрым.
Для начинающих Linux-программистов
Основы программирования в Linux - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
Предположим, что ваша система, как и системы обоих авторов, теперь генерирует сообщение о нарушении сегментации памяти. Если нет, читайте дальше. Вы узнаете, что делать, когда одна из ваших программ действительно сгенерирует сообщение о нарушении сегментации. Если вы не получили такого сообщения, но хотите поработать с этим примером во время чтения книги, когда первая из проблем, связанных с доступом к памяти, будет устранена, можно взять программу из файла debug4.c.
(gdb) run
Starting program: /home/neil/BLP4e/chapter10/debug3
Program received signal SIGSEGV, Segmentation fault.
0x0804846f in sort (a=0x804a040, n=5) at debug3.c:23
23 /* 23 */ if(a[j].key > a[j+1].key) {
(gdb)
Программа, как и прежде, выполняется неверно. Когда программа дает сбой, gdb указывает причину и местонахождение. Теперь вы можете выяснять первопричину проблемы.
В зависимости от ядра вашей системы, версий библиотеки С и компилятора сбой программы может произойти в другом месте, например в строке 25, когда элементы массива меняются местами, а не в строке 23, когда сравниваются поля key
элементов массива. Если это так, вы увидите следующее сообщение:
Program received signal SIGSEGV, Segmentation fault.
0x8000613 in sort (a=0x8001764, n=5) at debug3.c:25
25 /* 25 */ a[j] = a[j+1];
Вы все равно можете продолжать следить за примером сеанса работы gdb, который описывается далее.
Трассировка стека
Программа была остановлена при выполнении функции sort
в строке 23 исходного файла debug3.c. Если при компиляции вы не включили в программу дополнительную отладочную информацию ( cc -g
), то не сможете увидеть, где программа дала сбой, и использовать имена переменных для просмотра данных.
Увидеть, как вы добрались до этого места, можно с помощью команды backtrace
:
(gdb) backtrace
#0 0x0804846f in sort (a=0x804a040, n=5) at debug3.c:23
#1 0x08048583 in main() at debug3.c:37
(gdb)
Это очень простая программа и трассировка у нее короткая, т.к. вы не вызывали много функций из других функций. Вы только видите, что sort
была вызвана из main
в строке 37 того же файла debug3.c. Обычно проблема гораздо сложнее, и команда backtrace
применяется для определения маршрута, который привел к месту ошибки. Эта информация очень полезна при отладке функций, вызываемых из множества разных мест.
У команды backtrace
есть сокращенная форма bt
и для совместимости с другими отладчиками есть команда where
, выполняющая ту же функцию.
Просмотр переменных
Отладчик вывел данные в момент остановки программы, и в трассировке стека показаны значения аргументов функции.
Функция sort
была вызвана с параметром а
, значение которого 0х804а040. Это адрес массива. Обычно он в различных системах разный и зависит от используемых компилятора и операционной системы.
Сбойная строка 23 — сравнение одного элемента массива с другим:
/* 23 */ if (a[j].key > a[j+1].key) {
Отладчик можно применять для просмотра содержимого параметров функции, локальных переменных и глобальных данных. Команда print
отображает содержимое переменных и других выражений:
(gdb) print j
$1 = 4
Вы видите, что у локальной переменной j
значение 4
. Любые значения, выводимые командами gdb, подобными данной, сохраняются для будущего использования в псевдопеременных. В данном случае переменной $1
присвоено значение 4, на случай, если она вам позже понадобится. Последующие команды будут сохранять свои результаты в переменных $2
, $3
и т.д.
Значение переменной j
, равное 4, означает, что программа попыталась выполнить оператор
if (а[4].key > а[4+1].key)
У массива array
, который вы передали функции sort
, только пять элементов, которые пронумерованы от 0 до 4. Поэтому данный оператор считывает несуществующий элемент массива array[5]
. Переменная цикла j
приняла некорректное значение.
Если ваша программа завершилась в строке 25, система обнаружила чтение за пределами массива, только когда взялась за перестановку элементов массива, выполнив оператор
/* 25 */ а[j] = a[j+1];
который при j
, равной 4, дает в результате
а[4] = а[4+1];
Просмотреть элементы передаваемого массива можно, применив выражение в команде print
. В программе gdb вы можете использовать почти любое допустимое выражение языка С для вывода значения переменной, элемента массива или указателя.
(gdb) print а[3]
$2 = {data = "alex", '\0' , key = 1}
(gdb)
Отладчик gdb сохраняет результаты выполнения команд в псевдопеременных вида $< номер >
. Результат последней команды всегда хранится в псевдопеременной $
, а предыдущей — в $$
. Это позволяет результат одной команды использовать в другой. Например:
(gdb) print j
$3 = 4
(gdb) print a[$-1].key
$4 = 1
Вывод листинга программы
Вы можете в программе gdb вывести на экран исходный текст программы с помощью команды list
. Она выводит фрагмент кода, расположенного рядом с текущей позицией. Последующие вызовы list
выведут остальной текст. Команде list
можно задать в качестве аргумента имя функции, и команда отобразит фрагмент текста в этом месте программы, или можно указать пару номеров строк, и на экране появится текст программы, находящийся между этими строками.
(gdb) list
18 /* 18 */ int s = 1;
19 /* 19 */
20 /* 20 */ for(; i < n && s != 0; i++) {
21 /* 21 */ s = 0;
22 /* 22 */ for(j = 0; j < n; j++) {
23 /* 23 */ if(a[j].key > a[j+1].key) {
24 /* 24 */ item t = a[j];
25 /* 25 */ a[j] = a[j+1];
26 /* 26 */ a[j+1] = t;
27 /* 27 */ s++;
(gdb)
В строке 22 задано выполнение цикла до тех пор, пока переменная j
меньше n
. В данном случае n
равна 5, поэтому у j
будет последнее значение 4, слишком большое. Значение 4 приводит к сравнению а[4]
с а[5]
и возможной их перестановке. Единственное решение этой конкретной проблемы — исправить условие завершения цикла на следующее: j < n-1
.
Давайте внесем это изменение, назовем новую программу debug4.c, откомпилируем ее и попробуем снова выполнить.
/* 22 */ for(j = 0; j < n-1; j++) {
$ cc -g -o debug4 debug4.с
$ ./debug4
array[0] = {john, 2}
array[1] = {alex, 1}
array[2] = {bill, 3}
array[3] = {neil, 4}
array[4] = {rick, 5}
Программа все еще не работает, поскольку она вывела неверно отсортированный список. Попробуем применить gdb для пошагового выполнения программы.
Установка точек останова
Для обнаружения места сбоя в программе необходимо иметь возможность проследить за тем, что делает программа во время выполнения. Остановить ее в любой момент можно с помощью точек останова. Они останавливают программу и передают управление отладчику. Вы сможете проверить переменные и затем разрешить программе продолжить выполнение.
Читать дальшеИнтервал:
Закладка: