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 proindex = 0,1, 2, ... 999
. V poslední iteraci smyčkyfor
se však program pokusí získat přístup kfoo
. 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 rozsahu0, 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žefoo2
bude ukazovat na náhodné místo v paměti. Přístupfoo2
bude pravděpodobně mít za následek segfault.
- V případě, array
- 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ísto1000
, ale výše uvedené volání funkce by se snažit číst celé číslo data do paměti0
podle definicefoo
. - 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í backtrace
core
g 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++.