På denne siden:
- Oversikt
- Eksempler på vanlige segfaults
- Finn ut-av-grensene array referanser
- Sjekk shell grenser
- Bruk debuggere for å diagnostisere segfaults
oversikt
en segmenteringsfeil (aka segfault) er En Vanlig Tilstand som fører til at programmer krasjer; de er ofte knyttet til en fil Som Heter core
. Segfaults er forårsaket av et program som prøver å lese eller skrive en ulovlig minneplassering.Programminnet er delt inn i ulike segmenter: et tekstsegment for programinstruksjoner, et datasegment for variabler og matriser definert ved kompileringstid, et stakksegment for midlertidige (eller automatiske) variabler definert i subrutiner og funksjoner, og et heap-segment for variabler tildelt under kjøretid av funksjoner, for eksempel malloc
(I C) og allocate
(I Fortran). Hvis du vil ha mer, kan Du se om programsegmenter.
en segfault oppstår når en referanse til en variabel faller utenfor segmentet der variabelen ligger, eller når en skrive er forsøkt til en plassering som er i et skrivebeskyttet segment. I praksis er segfaults nesten alltid på grunn av å prøve å lese eller skrive et ikke-eksisterende arrayelement, ikke riktig definere en peker før du bruker den, eller (I C-programmer) ved et uhell å bruke en variabels verdi som en adresse (se scanf
eksempel nedenfor).
Eksempler på vanlige segfaults
- hvis du for eksempel ringer
memset()
som vist nedenfor, vil et program føre til segfault:memset((char *)0x0, 1, 100);
- Følgende tre tilfeller illustrerer de vanligste typene array-relaterte segfaults:
Case A /* "Array out of bounds" error valid indices for array foo are 0, 1, ... 999 */ int foo; for (int i = 0; i <= 1000 ; i++) foo = i;
/* Illegal memory access if value of n is not in the range 0, 1, ... 999 */ int n; int foo; for (int i = 0; i < n ; i++) foo = i;
/* Illegal memory access because no memory is allocated for foo2 */ float *foo, *foo2; foo = (float*)malloc(1000); foo2 = 1.0;
- I tilfelle a, Matrise
foo
er definert forindex = 0,1, 2, ... 999
. Men i den siste iterasjonen avfor
– sløyfen prøver programmet å få tilgang tilfoo
. Dette vil resultere i en segfault hvis den minneplasseringen ligger utenfor minnesegmentet derfoo
ligger. Selv om det ikke forårsaker en segfault, er det fortsatt en feil. - i tilfelle B kan integer
n
være en tilfeldig verdi. Som i tilfelle A, hvis det ikke er i området0, 1, ... 999
, kan det føre til en segfault. Enten det gjør det eller ikke, er det absolutt en feil. - i tilfelle C, tildeling av minne for variabel
foo2
har blitt oversett, såfoo2
vil peke til en tilfeldig plassering i minnet. Tilgang tilfoo2
vil trolig resultere i en segfault.
- I tilfelle a, Matrise
- En annen vanlig programmeringsfeil som fører til segfaults er tilsyn med bruk av pekere. For eksempel Forventer c-funksjonen
scanf()
adressen til en variabel som sin andre parameter.:int foo = 0; scanf("%d", foo); /* Note missing & sign ; correct usage would have been &foo */
variabelen
foo
kan defineres ved minneplassering1000
, men funksjonskallet ovenfor vil prøve å lese heltallsdata til minneplassering0
i henhold til definisjonen avfoo
. - En segfault oppstår når et program forsøker å operere på en minneplassering på en måte som ikke er tillatt (for eksempel forsøk på å skrive en skrivebeskyttet plassering vil resultere i en segfault).
- Segfaults kan også oppstå når programmet går tom for stack plass. Dette kan ikke være en feil i programmet, men kan skyldes i stedet for at skallet ditt angir stakkestørrelsesgrensen for liten.
Finn out-of-bounds matrisereferanser
De Fleste Fortran-kompilatorer har et alternativ som vil sette inn kode for å gjøre grensekontroll på alle matrisereferanser under kjøring. Hvis en tilgang faller utenfor indeksområdet som er definert for en matrise, stopper programmet og forteller deg hvor dette skjer. For De fleste Fortran-kompilatorer er alternativet-C
, eller-check
etterfulgt av et nøkkelord. Se kompilatorens brukerhåndbok for å få det nøyaktige alternativet. Bruk grensekontroll bare når feilsøking, siden det vil senke programmet. Noen c-kompilatorer har også et grensekontrollalternativ.
Sjekk shell grenser
som nevnt i det siste eksempelet ovenfor, noen segfault problemer er ikke på grunn av feil i programmet, men er forårsaket i stedet av systemminne grenser blir satt for lavt. Vanligvis er det grensen på stack størrelse som forårsaker denne typen problem. For å sjekke minnegrenser, bruk ulimit
kommandoen i bash
eller ksh
, eller limit
kommandoen i csh
eller tcsh
. Prøv å sette stacksize høyere, og kjør deretter programmet på nytt for å se om segfault går bort.
Bruk debuggere til å diagnostisere segfaults
hvis du ikke finner problemet på annen måte, kan du prøve en debugger. For eksempel kan DU bruke GNU velkjente debuggerGDB
for å vise backtrace av en core
fil dumpet av programmet; når programmer segfault, de vanligvis dumpe innholdet i (sin del av den) minne på tidspunktet for krasj i en core
fil. Start debuggeren med kommandoen gdb core
, og bruk deretter kommandoen backtrace
for å se hvor programmet var da det krasjet. Dette enkle trikset lar deg fokusere på den delen av koden.
hvis du brukerbacktrace
påcore
g-filen ikke finner problemet, må du kanskje kjøre programmet under feilsøkingskontroll, og deretter gå gjennom koden en funksjon, eller en kildekodelinje, om gangen. For å gjøre dette må du kompilere koden din uten optimalisering, og med -g
flagget, så informasjon om kildekodelinjer vil bli innebygd i den kjørbare filen. For mer, se Trinnvis eksempel for BRUK AV GDB i Emacs for å feilsøke Et c orC++ – program.