Indiana University Universiteit van Indiana Indiana University

Op deze pagina:

  • Overzicht
  • Voorbeelden van veel voorkomende segfaults
  • Zoeken out-of-bounds array referenties
  • kijk shell grenzen
  • Gebruik debuggers te diagnosticeren segfaults

Overzicht

Een segmentation fault (ook bekend als een segmentatie fout geeft) is een veel voorkomende aandoening die ervoor zorgt dat programma ‘ s crashen; ze worden vaak geassocieerd met een bestand met de naam core. Segfaults worden veroorzaakt door een programma dat probeert te lezen of schrijven van een illegale geheugenlocatie.

het Programma-geheugen is verdeeld in verschillende segmenten: een tekst-segment voor programma-instructies, een segment van gegevens voor de variabelen en arrays gedefinieerd tijdens het compileren, een stack segment voor tijdelijke (of automatische) variabelen die zijn gedefinieerd in subroutines en functies, en een hoop segment voor variabelen toegewezen tijdens runtime-functies, zoals malloc (in C) en allocate (in Fortran). Zie Over programmasegmenten voor meer informatie.

een segfault treedt op wanneer een verwijzing naar een variabele buiten het segment valt waar die variabele zich bevindt, of wanneer een schrijfpoging wordt gedaan naar een locatie die zich in een alleen-lezen segment bevindt. In de praktijk zijn segfaults bijna altijd te wijten aan het lezen of schrijven van een niet-bestaand array-element, het niet goed definiëren van een aanwijzer voordat het wordt gebruikt, of (in C-programma ‘ s) per ongeluk het gebruik van de waarde van een variabele als een adres (zie het scanf voorbeeld hieronder).

Voorbeelden van veel voorkomende segfaults

  • bijvoorbeeld, bellen memset() zoals hieronder getoond zou ertoe leiden dat een programma een segmentatie fout geeft:
    memset((char *)0x0, 1, 100);
  • De volgende drie gevallen illustreren de meest voorkomende vormen van array-gerelateerde segfaults:

    Geval Een

    /* "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;

    Geval 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;

    Zaak C

    /* Illegal memory access because no memory is allocated for foo2 */ float *foo, *foo2; foo = (float*)malloc(1000); foo2 = 1.0;

    • In geval van Een, array foo gedefinieerd voor index = 0,1, 2, ... 999. In de laatste iteratie van de lus for probeert het programma echter toegang te krijgen tot foo. Dit zal resulteren in een segfault als die geheugenlocatie buiten het geheugensegment ligt waar foo zich bevindt. Zelfs als het geen segfault veroorzaakt, is het nog steeds een bug.
    • in geval B kan integer n een willekeurige waarde zijn. Zoals in het geval A, als het niet in het bereik 0, 1, ... 999 ligt, kan het een segfault veroorzaken. Of het nu wel of niet, het is zeker een bug.
    • in geval C wordt de toewijzing van geheugen voor variabele foo2 over het hoofd gezien, dus foo2 wijst naar een willekeurige locatie in het geheugen. Toegang tot foo2 zal waarschijnlijk resulteren in een segfault.
  • een andere veel voorkomende programmeerfout die leidt tot segfaults is oversight in het gebruik van pointers. Bijvoorbeeld, de c functie scanf() verwacht het adres van een variabele als zijn tweede parameter; daarom zal het volgende waarschijnlijk ervoor zorgen dat het programma crasht met een segfault:
    int foo = 0; scanf("%d", foo); /* Note missing & sign ; correct usage would have been &foo */

    de variabele foo kan worden gedefinieerd op geheugenlocatie 1000, maar de bovenstaande functie aanroep zou proberen om integer gegevens in geheugenlocatie te lezen 0 volgens de definitie van foo.

  • een segfault zal optreden wanneer een programma probeert op een geheugenlocatie te werken op een manier die niet is toegestaan (bijvoorbeeld, pogingen om een alleen-lezen locatie te schrijven zouden resulteren in een segfault).
  • Segfaults kunnen ook optreden wanneer uw programma geen stackruimte meer heeft. Dit is misschien geen bug in je programma, maar het kan te wijten zijn aan het feit dat je shell de limiet voor stackgrootte te klein heeft ingesteld.

Find out-of-bounds array references

De meeste Fortran compilers hebben een optie die code invoegt om grenzen te controleren op alle array referenties tijdens runtime. Als een toegang buiten het indexbereik valt dat is gedefinieerd voor een array, zal het programma stoppen en je vertellen waar dit gebeurt. Voor de meeste Fortran-compilers is de optie -C, of -check gevolgd door een trefwoord. Zie de gebruikershandleiding van uw compiler om de exacte optie te krijgen. Gebruik bounds controle alleen bij het debuggen, omdat het zal vertragen uw programma. Sommige C compilers hebben ook een optie om grenzen te controleren.

Check shell limieten

zoals opgemerkt in het laatste voorbeeld hierboven, zijn sommige segfault problemen niet te wijten aan bugs in uw programma, maar worden in plaats daarvan veroorzaakt door systeemgeheugen limieten die te laag zijn ingesteld. Meestal is het de limiet op stapelgrootte die dit soort problemen veroorzaakt. Om geheugenlimieten te controleren, gebruik je de opdracht ulimit In bash of ksh, of de opdracht limit In csh of tcsh. Probeer het instellen van de stacksize hoger, en vervolgens opnieuw uitvoeren van uw programma om te zien of de segfault verdwijnt.

gebruik debuggers om segfaults te diagnosticeren

Als u het probleem niet op een andere manier kunt vinden, kunt u een debugger proberen. U kunt bijvoorbeeld GNU ‘ s bekende debugger GDB gebruiken om de backtrace te bekijken van een core bestand gedumpt door uw programma; wanneer programma ‘ s segfault, dumpen ze meestal de inhoud van (hun sectie van het) geheugen op het moment van de crash in een core bestand. Start uw debugger met het commando gdb core, en gebruik vervolgens het commando backtrace om te zien waar het programma was toen het crashte. Deze eenvoudige truc zal u toelaten om zich te concentreren op dat deel van de code.

als het gebruik van backtrace op het coreg bestand het probleem niet vindt, moet u het programma mogelijk uitvoeren onder debugger control, en dan stap door de code één functie, of één broncode regel, tegelijk. Om dit te doen, moet u uw code compileren zonder optimalisatie, en met de -g vlag, zodat informatie over broncode regels zal worden ingebed in het uitvoerbare bestand. Voor meer, zie stap-voor-stap voorbeeld voor het gebruik van GdB binnen Emacs om een C orC++ programma te debuggen.

gerelateerde documenten

Geef een antwoord

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *