PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : C++: catch(...){} fängt Speicherfehler?


mekakic
2011-12-12, 11:28:59
Wenn ich bei Pointeroperationen z.B. Blödsinn mache: read oder write Operationen auf Speicher, der mit nicht gehört oder NULL ist, durchführe. Dann lande ich meistens irgendwo in einem catch(...){}.

Meine Frage ist jetzt: bei was für Speichermisoperationen passiert das alles? Kann ich mich irgendwie darauf verlassen, dass bestimmt Fehler dort vom Exception Catch Block aufschlagen und gefangen werden?

Gibt es für diese Speicherfehler auch einen Typ? Bisher habe ich es nur mit einem catch(...) hinbekommen die zu fangen aber einen Typ für die gefunden.

Oder hängt das auch irgendwie von der Infrastruktur ab? Hardware und OS haben ja aus Security Gründen in den letzten 10 Jahren aufgerüstet was den Speicherschutz angeht. Passiert das fangen diese Speicher Exceptions auf einem alten Pentium3 mit Windows 2000 genauso wie unter meinem Core i5 und Windows 7 x64?

Ectoplasma
2011-12-12, 13:19:14
Mit catch(...) fängst du gnadenlos alles. Wenn du bestimmte Exceptions fangen möchtest, dann musst du das OS abhängig machen.

Wenn du unter Windows in C programmierst, dann schaue mal hier (http://msdn.microsoft.com/en-us/library/windows/desktop/ms681409%28v=vs.85%29.aspx), welche Möglichkeiten es da gibt.

Wenn du unter Windows in C++ programmierts, dann musst du einen eigenen Filter implementieren. Siehe hierzu SetUnhandledExceptionFilter (http://msdn.microsoft.com/en-us/library/windows/desktop/ms680634%28v=VS.85%29.aspx). Deine Filterfunktion muss die Exception auswerten. Dadurch kannst du dann eine von dir eigens definierte C++ Exception thrown, die du dann auch mit normalen C++ Catch - Blöcken fangen kannst.

Coda
2011-12-12, 13:34:23
Kompilier nicht mit /EHa und es passiert nicht mehr. Das ist sowieso böse. Es ist sogar noch böser, als catch(...) ohnehin schon ist.

Ectoplasma
2011-12-12, 13:45:21
Boost macht auch so einen Schweinkram mit catch(...). Nicht gerade sehr vorbildlich.

Dieses Konstrukt catch(const std::exception &e), wäre viel sauberer. Vorausgesetzt, dass alle Exceptions von std::exception abgeleitet wären. Hier hat man wenigstens eine ungefähre Ahnung, was geworfen wurde (e.what()).

Coda
2011-12-12, 15:04:47
catch(...) fängt normal auch keine structured exceptions (hardware traps). Das ist nur eine Unart des MS-Compilers mit /EHa. Deshalb soll er das ja auch aus machen.

mekakic
2011-12-12, 15:11:20
Okay ... warum ist das böse? Oder catch(...) allgemein?

Mir würde einfallen, dass solche Speicherfehler auf Anwendungsebene eigentlich immer auch Fehler sind und keine richtigen Ausnahmen... (dürfen passieren, sind aber die ... naja ... Ausnahme).

Wenn ich aber einen Call mache in irgendeine Funktion, von der ich vermute, dass die fehlerhaft ist (es würde mich überraschend wenn nicht), ist es doch von Vorteil, wenn mich der Call im Zweifel nicht mit runterzieht?

mekakic
2011-12-12, 15:15:45
catch(...) fängt normal auch keine structured exceptions (hardware traps). Das ist nur eine Unart des MS-Compilers mit /EHa. Deshalb soll er das ja auch aus machen.Ahh okay, also einfach nur abweichendes Verhalten? Solange man aber sowieso auf ewig auf MS Compiler festgenagelt wäre, spräche etwas dagegen dieses Verhalten mitzunehmen?

Solange das nicht die Fehlerbehandlung für kaputten Code ist, sondern einfach um zu vermeiden, dass einem bei einem externen Call alles um die Ohren fliegt?

Coda
2011-12-12, 15:25:00
Wenn irgendwo ein Speicherfehler auftritt, dann sind deine Datenstrukturen mit großer Sicherheit eh kaputt.

Das richtige Verhalten ist einfach zu crashen.

mekakic
2011-12-12, 15:59:15
Achso... ich dachte die Exception oder hier Hardware Trap wird dann ausgelöst, wenn der Zugriff erfolgt und nicht wenn der Zugriff schon passiert ist; d.h. möglicherweise etwas dann schon kaputt ist.

Ectoplasma
2011-12-12, 17:07:25
Achso... ich dachte die Exception oder hier Hardware Trap wird dann ausgelöst, wenn der Zugriff erfolgt und nicht wenn der Zugriff schon passiert ist; d.h. möglicherweise etwas dann schon kaputt ist.


Es ist etwas komplizierter. Eine Exception erfolgt, bevor etwas passiert. D.h., dass der falsche Zugriff nichts kaputt macht. Das Problem mit schadhaften Code ist aber, dass dieser Strukturen im Speicher zerstören kann, bei denen das System die Kontrolle an dein Programm bereits abgegeben hat. Das ist zum Beispiel bei einer Speicherallokation der Fall. Eine Exception wird jetzt nur doch dann vom System ausgelöst, wenn Speicher angesprochen wird, den du nicht vom System angefordert hast. Das OS schützt nur sich selbst und andere Prozesse, nicht aber das schadhafte Programm selbst.

Trap
2011-12-12, 19:13:43
Wenn irgendwo ein Speicherfehler auftritt, dann sind deine Datenstrukturen mit großer Sicherheit eh kaputt.
Es gibt auch harmlose SEH-Exceptions wie bei *(int*)0, oder 1/0. Wenn man da jetzt etwas als "böse" brandmarken will, dann auf jeden Fall catch(...) und nicht /EHa.

Coda
2011-12-12, 23:08:15
Wenn man Structured Exception Handling haben will, dann sollte man die Microsoft-Sprach-Extensions dafür verwenden und es nicht in catch reinpfuschen.

Portierbar ist es sowieso nicht.

Achso... ich dachte die Exception oder hier Hardware Trap wird dann ausgelöst, wenn der Zugriff erfolgt und nicht wenn der Zugriff schon passiert ist; d.h. möglicherweise etwas dann schon kaputt ist.
Das stimmt schon, dass die Exceptions ausgelöst wird, wenn die falsche Speicherseite gelesen wird. Dann geht nichts mehr kaputt. Aber davor war mit großer Sicherheit schon irgendwas nicht mehr korrekt.

Nach einer Null-Pointer-Exception weiterzumachen führt nur dazu, dass irgendwann dann doch wieder irgendwo ein Fehler auftritt, den man dann überhaupt nicht mehr zurückverfolgen kann. Oder der Code, der die Null-Pointer-Exception auslöst ist überhaupt nicht Exception-Safe.