Indiana University, Indiana University, Indiana University

Na této stránce:

  • Přehled
  • Příklady běžných segfault chyb
  • Najít out-of-bounds pole odkazy
  • Zkontrolujte, zda shell limity
  • Použití ladicí programy diagnostikovat segfault chyb

Přehled

segmentation fault (aka segfault) je běžný stav, který způsobuje havárie programů; oni jsou často spojeny s soubor, pojmenovaný core. Segfaults jsou způsobeny programem, který se snaží číst nebo zapisovat nelegální umístění paměti.

Program paměť je rozdělena do různých segmentů: textový segment pro program, návod, datový segment pro proměnné a pole definovány v době kompilace, stack segment pro dočasné (nebo automatické) proměnné definované v podprogramy a funkce, a heap segment pro proměnné alokované za běhu pomocí funkcí, jako je malloc (v C) a allocate (v jazyce Fortran). Více informací o programových segmentech.

segfault nastane, když odkaz na proměnnou spadá mimo segment, kde tuto proměnnou bydliště, nebo při zápisu se pokusil umístění, které je v read-only segmentu. V praxi, segfault chyb jsou téměř vždy vzhledem k pokusu o čtení nebo zápis neexistující prvek pole, není správně definovat ukazatel před použitím, nebo (v C programy) náhodně pomocí proměnné hodnotu jako adresu (viz scanf příklad níže).

Příklady běžných segfault chyb

  • například, volat memset(), jak je znázorněno níže by způsobit, že program zhavarovat:
    memset((char *)0x0, 1, 100);
  • následující tři případy ilustrují nejběžnější typy array-související segfault chyb:

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

    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;

    C

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

    • V případě, array foo je definována pro index = 0,1, 2, ... 999. V poslední iteraci smyčky for se však program pokusí získat přístup k foo. To bude mít za následek segfault, pokud toto umístění paměti leží mimo segment paměti, kde se nachází foo. I když to nezpůsobí segfault, je to stále chyba.
    • v případě B může být integer n libovolná náhodná hodnota. Stejně jako v případě a, pokud není v rozsahu 0, 1, ... 999, může způsobit segfault. Ať už ano nebo ne, je to určitě chyba.
    • V případě C, přidělování paměti pro proměnné foo2 byla přehlížena, takže foo2 bude ukazovat na náhodné místo v paměti. Přístup foo2 bude pravděpodobně mít za následek segfault.
  • další běžnou chybou programování, která vede k segfaultům, je dohled nad používáním ukazatelů. Například funkce C scanf() očekává adresu proměnné jako druhý parametr; proto následující pravděpodobně způsobí selhání programu se segfaultem:
    int foo = 0; scanf("%d", foo); /* Note missing & sign ; correct usage would have been &foo */

    proměnné foo může být definována v paměti místo 1000, ale výše uvedené volání funkce by se snažit číst celé číslo data do paměti 0 podle definice foo.

  • segfault nastane, když se program pokusí pracovat na paměťovém místě způsobem, který není povolen (například pokusy o zápis místa pouze pro čtení by vedly k segfault).
  • Segfaults může také dojít, když váš program vyčerpá zásobníku prostoru. Nemusí to být chyba ve vašem programu, ale může to být způsobeno tím, že váš shell nastavil limit velikosti zásobníku příliš malý.

zjistěte mimo hranice odkazy na pole

většina kompilátorů Fortran má možnost, která vloží kód pro kontrolu hranic všech odkazů na pole během běhu. Pokud přístup spadá mimo rozsah indexu definovaný pro pole, program se zastaví a řekne vám, kde k tomu dojde. Pro většinu kompilátorů Fortran je volba -C nebo -check následovaná klíčovým slovem. Přesnou možnost získáte v uživatelské příručce kompilátoru. Použijte kontrolu hranic pouze při ladění, protože zpomalí váš program. Některé kompilátory C mají také možnost kontroly hranic.

zkontrolujte limity shellu

Jak je uvedeno v posledním příkladu výše, některé problémy segfault nejsou způsobeny chybami ve vašem programu, ale jsou způsobeny příliš nízkými limity systémové paměti. Obvykle je to limit velikosti zásobníku, který způsobuje tento druh problému. Chcete-li zkontrolovat paměť limity, používání ulimit příkaz v bash nebo ksh nebo limit příkaz v csh nebo tcsh. Zkuste nastavit vyšší Velikost stacksize a znovu spusťte program, abyste zjistili, zda segfault zmizí.

použijte debuggery k diagnostice segfaultů

Pokud nemůžete najít problém jiným způsobem, můžete zkusit debugger. Například, můžete použít GNU je dobře známo, debugger GDB zobrazit backtrace core soubor kopačky od svého programu; kdykoliv programy segfault, obvykle výpisem obsahu (jejich části) paměti v době havárie do core soubor. Začněte debugger příkazem gdb core, a pak použít backtrace příkaz, aby viděli, kde byl program, když havaroval. Tento jednoduchý trik vám umožní zaměřit se na tuto část kódu.

Pokud pomocí backtracecoreg soubor nenajde problém, možná budete muset spustit program pod ladicí program ovládat, a pak krok prostřednictvím kódu, jednu funkci, nebo jeden zdrojový řádek kódu, v době,. K tomu, budete muset kompilovat váš kód bez optimalizace, a s -g vlajky, takže informace o zdrojový kód řádky budou vloženy do spustitelného souboru. Další informace naleznete v podrobném příkladu použití GDB v rámci Emacs k ladění programu C orC++.

související dokumenty

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *