Indiana University Indiana University Indiana University

På denne side:

  • oversigt
  • eksempler på almindelige segfaults
  • Find out-of-bounds array referencer
  • kontroller shell grænser
  • brug debuggere til diagnosticering af segfaults

oversigt

en segmenteringsfejl (aka segfault) er en almindelig tilstand, der får programmer til at gå ned; de er ofte forbundet med en fil med navnet core. Segfaults er forårsaget af et program forsøger at læse eller skrive en ulovlig hukommelse placering.

programhukommelse er opdelt i forskellige segmenter: et tekstsegment for programinstruktioner, et datasegment for variabler og arrays defineret på kompileringstidspunktet, et staksegment for midlertidige (eller automatiske) variabler defineret i underrutiner og funktioner og et heap-segment for variabler tildelt under runtime efter funktioner, såsommalloc (i C) ogallocate (i Fortran). For mere, se om programsegmenter.

en segmenteringsfejl opstår, når en henvisning til en variabel falder uden for det segment, hvor variablen befinder sig, eller når en skrivning forsøges til en placering, der er i et skrivebeskyttet segment. I praksis skyldes segfaults næsten altid at forsøge at læse eller skrive et ikke-eksisterende array-element, der ikke definerer en markør korrekt, før den bruges, eller (i C-programmer) ved et uheld at bruge en variabels værdi som en adresse (se scanf eksempel nedenfor).

eksempler på almindelige segfaults

  • for eksempel kalder memset() som vist nedenfor ville få ET program til segfault:
    memset((char *)0x0, 1, 100);
  • de følgende tre tilfælde illustrerer de mest almindelige typer array-relaterede 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;

    sag B

    /* 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;
    sag C

    /* Illegal memory access because no memory is allocated for foo2 */ float *foo, *foo2; foo = (float*)malloc(1000); foo2 = 1.0;
    • i tilfælde A, array foo er defineret for index = 0,1, 2, ... 999. I den sidste iteration affor loop forsøger programmet at få adgang tilfoo. Dette vil resultere i en segfault, hvis denne hukommelsesplacering ligger uden for hukommelsessegmentet, hvor foo ligger. Selvom det ikke forårsager en segfault, er det stadig en fejl.
    • i tilfælde B, heltal n kunne være en tilfældig værdi. Som i tilfælde A, hvis det ikke er i området 0, 1, ... 999, kan det forårsage en segfault. Uanset om det gør det eller ej, er det bestemt en fejl.
    • i tilfælde C, tildeling af hukommelse til variabel foo2er blevet overset, så foo2 vil pege på en tilfældig placering i hukommelsen. Adgang til foo2 vil sandsynligvis resultere i en segfault.
  • en anden almindelig programmeringsfejl, der fører til segfaults, er tilsyn med brugen af pointers. For eksempel C-funktionen scanf() forventer adressen på en variabel som dens anden parameter; derfor vil følgende sandsynligvis få programmet til at gå ned med en segfault:
    int foo = 0; scanf("%d", foo); /* Note missing & sign ; correct usage would have been &foo */

    variablen foo kan defineres på hukommelsesplacering 1000, men ovenstående funktionsopkald ville forsøge at læse heltalsdata til hukommelsesplacering 0 ifølge definitionen af foo.

  • der opstår en segfault, når ET program forsøger at operere på en hukommelsesplacering på en måde, der ikke er tilladt (for eksempel vil forsøg på at skrive en skrivebeskyttet placering resultere i en segfault).
  • Segfaults kan også forekomme, når dit program løber tør for stakplads. Dette er muligvis ikke en fejl i dit program, men kan i stedet skyldes, at din skal indstiller stakstørrelsesgrænsen for lille.
  • Find out-of-bounds array referencer

    de fleste Fortran compilere har en mulighed, der vil indsætte kode til at gøre grænser kontrol på alle array referencer under runtime. Hvis en adgang falder uden for det indeksområde, der er defineret for et array, stopper programmet og fortæller dig, hvor dette sker. For de fleste Fortran-kompilatorer er indstillingen -C eller -check efterfulgt af et nøgleord. Se din kompilators brugervejledning for at få den nøjagtige mulighed. Brug kun grænsekontrol, når du debugger, da det vil bremse dit program. Nogle C-kompilatorer har også en mulighed for grænsekontrol.

    kontroller shell-grænser

    som bemærket i det sidste eksempel ovenfor skyldes nogle segfault-problemer ikke fejl i dit program, men skyldes i stedet, at systemhukommelsesgrænser er indstillet for lave. Normalt er det grænsen for stack størrelse, der forårsager denne form for problem. For at kontrollere hukommelsesgrænser skal du bruge kommandoen ulimit i bash eller ksh eller kommandoen limit i csh div>eller tcsh. Prøv at indstille stackstørrelsen højere, og kør derefter dit program igen for at se, om segfault forsvinder.

    brug debuggere til at diagnosticere segfaults

    Hvis du ikke kan finde problemet på nogen anden måde, kan du prøve en debugger. For eksempel kan du bruge GNU ‘ s velkendte debugger GDB for at se backtrace af en core fil dumpet af dit program; når programmer segfault, dumper de normalt indholdet af (deres sektion af) hukommelsen på tidspunktet for nedbruddet i en core fil. Start din debugger med kommandoen gdb core, og brug derefter kommandoen backtrace for at se, hvor programmet var, da det styrtede ned. Dette enkle trick giver dig mulighed for at fokusere på den del af koden.

    Hvis du bruger backtracecoreg-filen ikke finder problemet, skal du muligvis køre programmet under debugger-kontrol og derefter gå gennem koden en funktion eller en kildekodelinje ad gangen. For at gøre dette skal du kompilere din kode uden optimering, og med -g flag, så oplysninger om kildekodelinjer vil blive indlejret i den eksekverbare fil. For mere, Se trin-for-trin eksempel for at bruge GDB i Emacs til at debugge et c orC++ – program.

    relaterede dokumenter