2.6 Отстраняване на грешки
2.6.1 Дебъгер
Дебъгерът, доставен с FreeBSD, се нарича gdb (GNU дебъгер). Стартира по команда
въпреки че повечето предпочитат да го стартират от Emacs. Можете да го направите така:
Използването на дебъгер ви позволява да изпълнявате програмата си в по-контролирана среда. Обикновено ще можете да преминавате през програмата ред по ред, да изследвате стойностите на променливите, да ги променяте, да кажете на дебъгера да изпълни програмата до определен момент и след това да спре и т.н. Можете дори да се свържете с вече работеща програма или да изтеглите дъмп файл, за да проучите причината за грешка в програмата. Възможно е дори да се отстранят грешки в ядрото, въпреки че това е малко по-сложно от отстраняването на грешки в потребителските приложения, за което е този раздел.
gdb има доста добра вградена помощна система, както и набор от информационни страници, така че този раздел ще се съсредоточи върху няколко основни команди.
И накрая, ако смятате, че е тромаво да издавате команди в стил на команден ред в текстов режим, има графичен инструмент xxgdb в колекцията от портове за него.
Този раздел е предназначен да бъде въведение в използването на gdb и не обхваща специални теми като отстраняване на грешки в ядрото.
2.6.2 Изпълнение на програмата в дебъгера
За да извлечете максимума от използването на gdb, трябва да компилирате програмата с опцията -g. Дебъгерът ще работи и без тази опция, но ще можете да видите само името на текущата функция, но не и нейния изходен код. Ако видите съобщение като това:
когато стартирате gdb, установете, че програмата не е компилирана с опцията -g.
В подканата на gdb въведете break main . Това ще каже на дебъгера да пропусне кода за предварителна подготовка.програми и започнете веднага с вашия код. Сега издайте команда за стартиране, за да стартирате програмата - тя ще започне да се изпълнява с подготвителен код и след това ще бъде спряна от дебъгера, когато се извика main(). (Ако някога сте се чудили откъде се извиква main(), сега трябва да знаете!).
Ето един прост пример за това как да хванете грешка в програма с помощта на gdb. Това е нашата програма (с умишлена грешка):
Тази програма задава променливата i на 5 и я предава на функцията bazz(), която отпечатва числото, което сме предали.
При компилирането и стартирането на програмата получихме
Това не е това, което очаквахме! Време е да видим какво става!
Чакай малко! Как параметърът anint в крайна сметка е 4231? Не му ли дадохме стойност 5 във функцията main()? Нека да преминем към функцията main() и да погледнем там.
Боже мой! Съдейки по кода, забравихме да инициализираме променливата i. Какво искаше да направиш
но забравих за реда i=5; . Тъй като не сме задали начална стойност за i, променливата приема произволна стойност, която се появява в съответната област на паметта, когато програмата работи, и в нашия случай това се оказа числото 4231.
Забележка:gdb отпечатва стека на повикванията, когато извикваме или се връщаме от функция, дори ако използваме командите нагоре и надолу, за да се придвижим нагоре в стека. Това отпечатва името на функцията и стойностите на нейните аргументи, което ни помага да следим къде сме и какво се случва. (Стекът е областта, където програмата съхранява информация за аргументите, предадени на функциите, и къде да отиде, след като функцията се върне.)
2.6.3 Преглед на дъмп файла
Дъмп файлът е най-общо казано файл, съдържащ пълно изображение на процес в момента, в който се е сбил. „Добротов старите времена програмистите използваха да отпечатват шестнадесетични дъмп файлове и да проучват препратките към машинния код, но сега животът е малко по-лесен. По-специално, на FreeBSD и други системи, базирани на 4.4BSD, дъмп файловете се наричат progname .core, а не само core, за да стане ясно на коя програма принадлежи съответният дъмп файл.
За да прегледате дъмп файла, стартирайте gdb нормално. Вместо да издавате команда break или run, въведете
Ако не сте в същата директория като дъмп файла, трябва първо да изпълните командата dir /path/to/core/file.
Трябва да видите нещо като следното:
В този случай програмата се нарича a.out, така че дъмп файлът се нарича a.out.core. Можем да видим, че програмата се срина, защото се опита да получи достъп до област от паметта, до която не можа да получи достъп във функцията bazz.
Функцията end() е извикана, когато програмата се срине; в този случай функцията bazz() е извикана от main().
2.6.4 Свързване към работеща програма
Една от изключителните характеристики на gdb е, че може да се закачи към програма, която вече работи. Разбира се, това предполага, че имате достатъчно правомощия за това. Има проблем в ситуацията, в която искате да проследите дъщерния процес, но дебъгерът ви позволява да проследите само родителския процес.
В тази ситуация трябва да стартирате друг gdb дебъгер, да използвате командата ps, за да намерите идентификатора на процеса на дъщерния процес и да издадете командата
към gdb и след това отстранете грешки в програмата по обичайния начин.
``Всичко е наред,'' сигурно си мислите, ``но докато направя всичко това, създаденият процес ще е свършил работата си''. Може би не, скъпачетец и ето как се прави (според информационните страници на програмата gdb):
Сега всичко, което трябва да направите, е да се прикачите към създадения процес, да зададете променливата PauseMode на 0 и да изчакате извикването на sleep() да се върне!
предишна | У дома | Следващия |
направи | нагоре | Използване на Emacs като среда за разработка |
За въпроси, свързани с FreeBSD, прочетете документацията, преди да пишете на . За въпроси, свързани с тази документация, пишете на. За въпроси, свързани с българския превод на документация, пишете на .