Wat veroorzaakt een SIGSEGV

Ik moet de hoofdoorzaak van de segmentatiefout (SIGSEGV) weten en weten hoe ik ermee om moet gaan.


Antwoord 1, autoriteit 100%

Wikipedia heeft het antwoord, samen met een aantal andere bronnen.

Een segfault betekent in feite dat je iets slechts hebt gedaan met pointers. Dit is waarschijnlijk een segfault:

char *c = NULL;
...
*c; // dereferencing a NULL pointer

Of dit:

char *c = "Hello";
...
c[10] = 'z'; // out of bounds, or in this case, writing into read-only memory

Of misschien dit:

char *c = new char[10];
...
delete [] c;
...
c[2] = 'z'; // accessing freed memory

In elk geval hetzelfde basisprincipe: je doet iets met geheugen dat niet van jou is.


Antwoord 2, autoriteit 18%

Er zijn verschillende oorzaken van segmentatiefouten, maar in wezen benadert u het geheugen verkeerd. Dit kan worden veroorzaakt door de verwijzing naar een null-aanwijzer, of door te proberen het alleen-lezen geheugen te wijzigen, of door een aanwijzer te gebruiken naar een plek die niet is toegewezen aan de geheugenruimte van uw proces (dit betekent waarschijnlijk dat u een getal als aanwijzer probeert te gebruiken , of u hebt een aanwijzer te ver verhoogd). Op sommige machines is het mogelijk dat een verkeerd uitgelijnde toegang via een aanwijzer het probleem ook veroorzaakt – als je bijvoorbeeld een oneven adres hebt en er een even aantal bytes van probeert te lezen (dat kan in plaats daarvan SIGBUS genereren).


Antwoord 3, autoriteit 8%

een ongeldige/null-aanwijzer gebruiken? Overschrijding van de grenzen van een array? Het is nogal moeilijk om specifiek te zijn zonder een voorbeeldcode.

In wezen probeert u toegang te krijgen tot geheugen dat niet tot uw programma behoort, dus het besturingssysteem maakt het af.


Antwoord 4, autoriteit 7%

Hier is een voorbeeld van SIGSEGV.

root@pierr-desktop:/opt/playGround# cat test.c
int main()
{
     int * p ;
     * p = 0x1234;
     return 0 ;
}
root@pierr-desktop:/opt/playGround# g++ -o test test.c  
root@pierr-desktop:/opt/playGround# ./test 
Segmentation fault

En hier is het detail.

Hoe ermee om te gaan?

  1. Vermijd het zoveel mogelijk in de
    eerste plaats.

    Programmeer defensief: gebruik assert(), controleer op NULL-aanwijzer , controleer op bufferoverloop.

    Gebruik statische analysetools om uw code te onderzoeken.

    compileer uw code met -Werror -Wall.

    Heeft iemand uw code beoordeeld.

  2. Toen dat echt gebeurde.

    Bestudeer je code zorgvuldig.

    Controleer wat je hebt veranderd sinds de laatste keer dat je code zonder crashes succesvol werd uitgevoerd.

    Hopelijk geeft gdb je een call-stack zodat je weet waar de crash is gebeurd.


EDIT: sorry voor de haast. Het moet *p = 0x1234; zijn in plaats van p = 0x1234;


Antwoord 5, autoriteit 4%

SigSegV betekent een signaal voor een schending van de geheugentoegang, waarbij wordt geprobeerd te lezen of te schrijven van/naar een geheugengebied waartoe uw proces geen toegang heeft. Dit zijn geen C- of C++-uitzonderingen en u kunt geen signalen opvangen. Het is inderdaad mogelijk om een ​​signaal-handler te schrijven die het probleem negeert en de continue uitvoering van je onstabiele programma in ongedefinieerde staat mogelijk maakt, maar het moet duidelijk zijn dat dit een heel slecht idee is.

Meestal komt dit door een bug in het programma. Het opgegeven geheugenadres kan helpen bij het debuggen van wat het probleem is (als het bijna nul is, is het waarschijnlijk een null-pointer dereferentie, als het adres zoiets is als 0xadcedfe dan is het een opzettelijke beveiliging of een foutopsporingscontrole, enz. )

Een manier om het signaal te ‘vangen’ is om je spullen in een apart onderliggend proces te laten lopen dat dan abrupt kan worden beëindigd zonder dat je hoofdproces ermee stopt. Het vinden van de oorzaak en het oplossen ervan heeft uiteraard de voorkeur boven dit soort tijdelijke oplossingen.


Antwoord 6, autoriteit 2%

Segmentatiefout treedt op wanneer u toegang krijgt tot geheugen dat niet door het programma is gedeclareerd. U kunt dit doen door middel van pointers, d.w.z. via geheugenadressen. Of dit kan ook te wijten zijn aan stackoverflow, bijvoorbeeld:

void rec_func() {int q = 5; rec_func();}
int main() {rec_func();}

Deze aanroep blijft stapelgeheugen in beslag nemen totdat het volledig is gevuld en er uiteindelijk sprake is van stackoverflow.
Opmerking: het is misschien niet zichtbaar in sommige competitieve vragen, omdat het eerst tot timeouterr leidt, maar voor degenen waarbij de time-out niet optreedt, is het moeilijk om SIGSEGV te achterhalen.


Antwoord 7

De oorspronkelijke oorzaak kan ook te weinig geheugen zijn.

LEAVE A REPLY

Please enter your comment!
Please enter your name here

3 + 16 =

Other episodes