Debugging under UNIX
Introduksjon
Debugging under UNIX er for mange ganske annerledes enn fra DOS/Windows, der debuggeren gjerne er integrert med kompilator og editor i et utviklingsmiljø. På UNIX-plattformen er ofte dette utviklingsmiljøet delt opp i flere enkeltprogrammer. Dette fører til at man ikke er bundet til en enkelt debugger, men kan velge og vrake i flere programmer som finnes tilgjengelig.
Kompilering av programmer for debugging
For at et program skal kunne debugges, må det kompileres slik at en del tilleggsinformasjon blir lagt med. Bruker man gcc, g++, f90 eller f77-kompilatoren, gjøres dette ved å gi opsjonen -g til kompilatoren. Merk at mange debuggere ikke fullt ut vil takle språk som ikke er så mye brukt som C.
Dersom vi har et program nalle, vil vi vanligvis gjøre følgende for å kompilere det:
gcc -o nalle.o -c nalle.c gcc -o nalle nalle.o
For å få med debuggings-informasjon tar vi med -g:
gcc -g -o nalle.o -c nalle.c
gcc -g -o nalle nalle.o
Merk at programfilen blir mye større når debuggings-informasjon kompileres med.
Debugging
Under har jeg kikket nærmere på en del av de programmene som finnes for debugging på NTNU. Det er ikke sikkert at alle vil være installert på den maskinen du jobber på. Min personlige favoritt er kombinasjon av emacs og gdb.
GDB - The GNU DeBugger
Informasjon om gdb finnes i GNU info tree. Dette aksesseres ved å utføre kommandoen info gdb eller med C-h i i emacs. GDB virker for C og C++, med begrenset støtte for Modula-2 og Fortran.
GDB startes vanligvis som gdb [program] der program er den kjørbare filen til programmet som skal debugges. Det er også mulig å starte gdb slik at den knytter seg til en prosess som allerede kjører, eller å starte den slik at den ser på core-fila til et program som har terminert abnormalt.
Når debugger kommer opp vil du få et prompt (gdb) der du kan skrive inn kommandoer. En nyttig kommando er help som gir en oversikt over ulike kategorier av kommandoer, der det er mulig å se nærmere på hver kategori. Hjelp om enkeltkommandoer fåes med h [kommando]
Når et program er klart til å kjøres fra gdb, er en vanlig måte å sette igang debuggingen på å gi følgende to kommandoer:
(gdb) b main (gdb) r
Den første kommandoen setter et breakpoint i rutinen main, altså helt først i programmet. Den neste kommandoen kjører programmet helt til den kommer til start av main-prosedyren hvor den treffer et breakpoint og stopper.
Det finnes flere måter å gå gjennom et program. En av de har vi allerede vist, ved at det er mulig å sette breakpoints. Breakpoints kan bl.a. settes på disse måtene:
- (gdb) b [funksjon]
- (gdb) b [linjenummer]
- (gdb) b [kildekodefil]:[linjenr]
Når et program har stoppet, kan du kjøre programmet videre fra der det ble stoppet med kommandoen c. Programmet vil da kjøre videre inntil en av følgende inntreffer:
- Programmet avslutter normalt
- Programmet avslutter abnormalt
- Debuggeren finner et breakpoint
Når et breakpoint settes, assosieres dette med et nummer. Man kan da i ettertid skru et breakpoint på eller av med kommandoen enable [nr] og disable [nr].
To andre viktige kommandoer er n (next) og s (step). Next utfører en kommandolinje og stopper. Hvis det er et funksjonskall på linjen, utføres funksjonskallet før den stopper. Step gjør stort sett det samme, men stopper på første linje av funksjonen.
For å se på variabler finnes kommandoene print og display som begge tar variabelnavnet som argument. Den første skriver ut verdien av variabelen, mens den andre kontinuerlig viser verdien. Med display assosieres et nummer, s.a. man kan skru det av med undisplay [nr].
Kombinasjonen GDB/emacs
GDB kan startes fra emacs, og dette er etter mitt syn en mer praktisk måte å jobbe på. GDB startes med kommandoen M-x gdb. Du får da et spørsmål om hvilket program som skal debugges, skriv så inn navnet på programfilen.
Den store forskjellen oppleves når du begynner å debugge. emacs starter opp med gdb i ett vindu, mens kildekoden dukker opp i neste vindu. Etter hvert som debuggingen går fremover, vises det med en pil hvor i kildekoden debuggeren befinner seg.
ddd - gdb/dbx wrapper
Dette er egentlig ikke en debugger i den forstand at programmet selv foretar debugging. ddd er derimot et overbygg til andre debuggere (gdb og dbx) og har et grafisk brukergrensesnitt mot disse. Programmet bruker i utgangspunktet gdb til debugging, men kan med opsjonen --dbx settes til å benytte denne istedenfor. Programmet startes med ddd [programfil]. Andre måter å starte ddd får du ved å skrive man ddd.
ddd er pr. 10. februar 2002 kun installert på solarislogin.stud.ntnu.no.
dbx
Dette er en annen debugger som kanskje finnes på ditt system. Det startes med dbx [programfil] og er tekstbasert som gdb. Se man dbx for mer informasjon om programmet. Selv har jeg ikke hatt behov for å bruke programmet, men det kan hende at du bruker et språk som gdb ikke forstår. dbx skjønner Pascal og assembler fra h.h.v. kompilatorene pc og as.
Andre nyttige verktøy
Programmet strace lister opp alle kall til kjernen som gjøres av programmet mens det kjører. På denne måten kan det være mulig å oppdage rare ting i programmet.
Noen maskiner har også installert et program som heter purify, som kan brukes til å finne pekerfeil og minnelekkasjer til et program.
Debugging av prosesser som bruker fork()
Dette er et problemfelt, og inntil noen korrigerer meg, så vet jeg kun om en måte å løse dette problemet på, nemlig ved å gjøre større eller mindre forandringer i koden.
En mulighet er at fork() ikke kalles ved debugging, dette kan fungere dersom ikke programmet er avhengig av og baserer seg på at det kjører fork(). Da kan fork() utelates, f.eks. med
#ifndef DEBUG fork() #endif
der DEBUG settes med argumentet -DDEBUG til kompilatoren.
En annen mulighet (som jeg selv ikke har eksperimentert med) er at de to prosesstrådene settes til å sove permanent etter fork()-kommandoen, f.eks. ved en konstruksjon som
int sove_videre = 1; parent_id = fork(); while(sove_videre) sleep(1);
Her vil begge trådene sove i en uendelig løkke som ikke er CPU-intensiv. Så kan det startes en debugger-sesjon for hver av de to trådene der debuggeren attacher rett til prosessen, sove_videre kan settes til 0 fra debuggeren, og trådene kan kjøres kontrollert videre. I teorien skulle dette virke veldig bra, men jeg har ikke prøvd dette selv. Dersom noen har bedre forslag til hvordan dette kan gjøres, tas de imot med glede, og vil bli inkludert på denne siden.
| Languages: | Comments: | 0 | Aid: | 108 | User rating: |
|
|
| Last updated: | 2007-08-09 | Author: | krismika | Read: | 4281 times |