Fang segfaults in C
Ich habe ein Programm, dass segfaults von Zeiger-Arithmetik manchmal. Ich weiß, das passiert, aber ich kann nicht einfach überprüfen, vor der Zeit, um zu sehen, ob es segfaults oder nicht - entweder kann ich die "pre-scan" input-Daten, um zu sehen, wenn es zu einem segfault (das kann unmöglich sein, zu bestimmen), oder kann ich refit, es nicht zu verwenden, Zeiger-Arithmetik, die verlangen einen deutlich größeren Umfang der Arbeit, oder ich kann versuchen, Sie zu fangen einen segfault. Also meine Frage:
1) Wie in C, kann ich fangen einen segfault? Ich weiß etwas in der OS-Ursachen ein segfault, aber was kann ein C-Programm tun, in dem Fall, dass es segfaults zu sterben ein bisschen mehr anmutig als nur Segmentation fault
?
2) Wie Mobil ist das?
Ich denke, das ist eine höchst unportabel Verhalten, so dass, wenn Sie irgendeinen code zu fangen segfault, bitte sagen Sie mir, was Sie arbeitet. Ich bin auf Mac OS X, aber ich möchte mein Programm funktioniert auf so vielen Plattformen, wie es kann, und ich will sehen, was meine Optionen sind.
Und keine Sorge - im Grunde alles was ich will zu tun ist, drucken Sie eine benutzerfreundlichere Fehlermeldung und kostenlos einige malloc()
ed-Speicher, und dann sterben. Ich bin nicht der Planung auf, einfach zu ignorieren, alle segfaults, die ich bekommen und Pflügen vor.
- Drucken Sie die Fehlermeldung; nicht den Speicher frei, wie die Chancen sind gut, dass Ihr Gedächtnis-system ist gestört, wenn die seg Fehler passiert.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Müssen Sie definieren einen signal-handler. Dies geschieht auf Unix-Systemen mit Hilfe der Funktion
sigaction
. Ich habe dies getan, mit dem gleichen code auf Fedora 64 - und 32-bit-und auf Sun Solaris.Gut, SIGSEGV ist auffangbaren, und das ist POSIX, so ist es tragbar, in diesem Sinne.
Bu bin ich besorgt, dass Sie scheinen zu wollen, Griff der segfault, anstatt das problem zu beheben, die bewirkt, dass der segfault. Wenn ich auswählen müsste, ob es war der OS ein Verschulden trifft, oder mein eigener code, ich weiß, was ich wählen würde. Ich schlage vor, Sie jagen Sie, die Fehler zu beheben, dann schreibt man einen Testfall, um sicherzustellen, dass es nie beißt Sie wieder.
Können Sie die Funktion signal installieren Sie einen neuen Signalhandler für das signal:
Etwas wie den folgenden code:
Den sicheren Aktionen in einem signal-handler sind sehr begrenzt. Es ist unsicher, rufen Sie eine library-Funktion nicht bekannt zu sein, re-entrant, ausgeschlossen werden, zum Beispiel
free()
undprintf()
. Best practice ist, um eine variable zu setzen und zurück, aber das hilft Ihnen nicht sehr viel. Es ist auch sicher zu verwenden Systemaufrufe wiewrite()
.Beachten Sie, dass in den beiden backtrace Beispiele, die hier gegeben werden, die
backtrace_symbols_fd()
Funktion sicher, weil es verwendet die raw-fd direkt, aber der Aufruffprintf()
ist falsch und sollte ersetzt werden durch eine Verwendung vonwrite()
.Ich denke, dass Sie versuchen, ein problem zu lösen, dass nicht existiert. Zumindest arbeiten Sie am falschen Ende. Sie werden nicht in der Lage zu fangen einem segmentation-fault, da dieser Fehler/die Ausnahme wird ausgelöst, indem Sie die OS (es ist verursacht durch Ihr Programm, das OS nur fängt es).
Ich würde Ihnen raten, Ihre Strategie zu überdenken in Bezug auf den input: Warum ist es unmöglich zu desinfizieren sind es? Die wichtigsten zu tun ist, die Größe überprüfen, für das die C stdlib hat entsprechende Funktionen. Dann natürlich würden Sie haben zu prüfen, für die gültige Eingabe in Bezug auf den Inhalt. Ja, dies wird wahrscheinlich Ergebnis in eine Menge Arbeit, aber es ist der einzige Weg zu schreiben, eine robuste Programm.
EDIT: ich bin nicht viel von einem C-Experte, wusste gar nicht, dass auch ein "segmentation fault" gehandhabt werden könnten, die von einem signal-handler. Trotzdem, ich denke, es ist nicht der richtige Weg für den oben genannten Gründen.
Benötigen Sie ein SIGSEGV-handler, dieser sieht ziemlich anständig.
signal handling ist (relativ) portabel auf unix-Maschinen (dies schließt mac und linux). Die großen Unterschiede sind in der exception detail, das als argument übergeben wird, um die signal-handling-routine. Sorrty, aber Sie müssen wahrscheinlich ein paar der #ganzen IFDEFs für, dass, wenn Sie drucken möchten mehr vernünftige Fehlermeldungen (wie, wo und aufgrund welcher Adresse der Fehler passiert ist) ...
ok, hier ist ein code-fragment für Sie zu beginnen mit:
Ihre Aufgabe ist es:
in der Theorie, Sie könnte auch patch der pc in der signal-handler (nach der fehlerhaften Anweisung), und fahren Sie Fort. Allerdings, typische signal-Handler entweder exit() oder longjmp() wieder in einen sicheren Platz in der main.
hinsichtlich
Es ist ein Beispiel, wie zu fangen, SIGSEGV und drucken Sie einen stack-trace mit glibc ' s backtrace() hier:
wie generieren Sie einen stacktrace, wenn meine C++ - app stürzt ab
Können Sie diese zu fangen Ihre segfault und reinigen, aber seien Sie gewarnt: Sie sollten nicht so viel Zeug in einem signal-handler, vor allem Dinge, die umfassen telefonieren wie malloc(). Es gibt eine Menge Anrufe, die nicht-signal-safe, und Sie können am Ende Schießen sich in den Fuß, wenn Sie machen, sagen wir, einem Aufruf von malloc innerhalb von malloc.