Seg Fault abfangen



  • Frage 1:

    geht sowas?

    myClass* mc;
    
    try
    {
        mc->foo();
    }
    catch( ... )
    {
        std::cerr << "Segfault" << std::endl;
    }
    

    Antwort kann ich mir denken: nein, geht nicht (zumindest, was ich so aufgeschnappt hab)

    Frage 2 daher:
    Warum nicht? Dazu hab ich leider nichts gefunden



  • Weil alle Checks, die das ermöglichen würden, sehr auf die Laufzeit gehen würden. Und das war für die Sprache C++ nicht gewünscht (was keinen Compilerhersteller daran hindert, sowas dennoch zu implementieren).



  • danke

    waer halt um einiges praktischer als dieses ewige pruefen auf NULL 🙂



  • zwutz schrieb:

    waer halt um einiges praktischer als dieses ewige pruefen auf NULL 🙂

    Vor diesem Fehler schützt dich das auch nicht, da mc in diesem Beispiel nicht NULL ist (vorausgesetzt, das ganze findet in einer Funktion statt).



  • Ist ein try-catch nicht genauso nervig wie ein if 0?
    Wie man sieht: Fehlerbehandlung muß man so oder so machen. Die if-Abfrage is halt nur eine Variante.



  • das alle immer auf beispielhaften Codestücken rumreiten müssen -.-

    :p

    Bulli schrieb:

    Ist ein try-catch nicht genauso nervig wie ein if 0?
    Wie man sieht: Fehlerbehandlung muß man so oder so machen. Die if-Abfrage is halt nur eine Variante.

    nicht, wenn mehrere potentielle Fehlerquellen in einem Ausdruck erscheinen

    (Achtung, überspitztes Beispiel!)

    classA->getB()->getC()->getD()->die()
    

    hier ist ein

    if ( !classA->getB() || !classA->getB()->getC() || !classA->getB()->getC()->getD() )
    {
        return;
    }
    

    nicht wirklich das wahre 😉



  • ja, kann man abfangen (seh exception). ist aber nicht sinnvoll.



  • LordJaxom schrieb:

    Weil alle Checks, die das ermoeglichen wuerden, sehr auf die Laufzeit gehen wuerden. Und das war fuer die Sprache C++ nicht gewuenscht (was keinen Compilerhersteller daran hindert, sowas dennoch zu implementieren).

    jetzt muss ich doch noch einmal nachhacken... Wie genau arbeiten Exceptions? Ich haette vermutet, dass wenn der Code im try einen Fehler verursacht wird nach einen entsprechenden catch gesucht. Wenn keiner gefunden wird, wird er an die naechsthoehere Stelle weitergereicht. Wenn das OS erreicht wird, wird das Programm beendet.
    Das wuerde aber nicht erklaeren, was an einer Pruefung auf einen segfault so viel laufzeitkritischer als an anderen Exceptions (wie bad_alloc) waere



  • zwutz schrieb:

    Das wuerde aber nicht erklaeren, was an einer Pruefung auf einen segfault so viel laufzeitkritischer als an anderen Exceptions (wie bad_alloc) waere

    Ist es auch nicht.

    aber nicht jeder zugriff auf einen ungültigen zeiger verursacht einen seg fault...



  • @zwutz: Nur als Hinweis (Law of Demeter): http://de.wikipedia.org/wiki/Gesetz_von_Demeter
    ➡ Würde dein Problem ein wenig entschärfen.
    Simon



  • Mh, ich hab hier gerade folgenden Code vor mir:

    void sigSegv()
    {
    	signal(SIGSEGV, SIG_IGN);
    
    	net.send(HAS_N, "[!] Got segmentation fault signal; please report this crash", NULL);
    	net.irc.send("QUIT :Got segmentation fault signal; please report this crash", NULL);
    
    #ifdef HAVE_DEBUG
    // debugging stuff
    #endif
    	dumpBacktrace();
    }
    
    #define register_signal(x, y) \
    {	\
    	memset(&sv, 0, sizeof(sv)); \
    	sv.sa_handler = y;	\
    	sigaction(x, &sv, NULL);	\
    }
    
    void signalHandling()
    {
    	struct sigaction sv;
    
    	register_signal(SIGPIPE, SIG_IGN);
    	register_signal(SIGCHLD, (sighandler_t) sigChild);
    	register_signal(SIGTERM, (sighandler_t) sigTerm);
    	register_signal(SIGINT, (sighandler_t) sigInt);
    	register_signal(SIGHUP, (sighandler_t) sigHup);
    	register_signal(SIGUSR1, (sighandler_t) sigUpdated);
    	register_signal(SIGUSR2, (sighandler_t) sigUpdateFailed);
    #ifndef HAVE_DEBUG
    	register_signal(SIGSEGV, (sighandler_t) sigSegv);
    #endif
    	register_signal(SIGXCPU, (sighandler_t) sigCpuTime);
    }
    

    Das ganze funktioniert zum. unter Linux, wird aber wohl nicht das sein, wass du moechtest, denn es macht nichts anderes, als im Fehlerfall das Programm sauber zu beenden und dem Entwickler zu sagen was wo passiert ist 🙂



  • zwutz schrieb:

    Das wuerde aber nicht erklaeren, was an einer Pruefung auf einen segfault so viel laufzeitkritischer als an anderen Exceptions (wie bad_alloc) waere

    Weil solche Überprüfungen Aufgabe der Laufzeit (OS) wären, die von dir erwähnten aber zur Standardbibliothek gehören. Im Programmcode der Standardbibliothek steht sowas wie if (alloc(...) == 0) throw bad_alloc(); . Es steht Dir natürlich frei, vor jedem Zeigerzugriff ein if (!p) throw bad_ptr(); zu machen. Der Compiler macht das jedenfalls nicht. Aber, wie schon erwähnt, vor Segfaults die aus einem Zugriff auf eine Speicherstelle ungleich NULL resultieren schützt Dich das ohnehin auch nicht.


Anmelden zum Antworten