| 

.NET C# Java Javascript Exception

2
ein beispiel:

MeinObject* aufDemHeap = new MeinObject("abc");
int x = a / b;
delete aufDemHeap;

die division a/b könnte ja fehlschlagen. wie kann ich trotzdem sicherstellen, dass meine objekt-Instanz gelöscht wird?
News:
30.08.2009
winmain 123 1 3
5 Antworten
3
Das Beispiel ist meiner Meinung nach, etwas schlecht gewählt. Etwas dergleichen, würde man einfach mit einem
if(b!=0)

regeln.

Aber um auf deine Frage zurückzukommen. Der einfachste Weg wäre, einfach zu überprüfen, ob die Daten valide sind. Sind sie es nicht, wird der Codeteil schlichtweg nicht ausgeführt und es entsteht kein Fehler.

Sollte das nicht gehen, würden sich Exceptions eignen. Dabei reservierst du erst Speicher auf dem Heap, schließt den Code, der ggf eine Exception wirft, in einen try{} Block ein und fängst eine Exception mit dem catch() Block.
Einige C++ Funktionen werfen selbstständig Exceptions, zB "new". Bei anderen musst du dann selbst dafür sorgen, dass eine Exception geworfen wird.

zB
MeinObject *aufDemHeap = new MeinObject("abc");
try
{
x=a/b;
if(x==std::numeric_limits<float>::infitive
|| x==-std::numeric_limits<float>::infitive)
throw new Exception("Fehler beim dividieren");

std::cout << x;
delete aufDemHeap;
}
catch(Exception e)
{
std::cout << e;
delete aufDemHeap;
}


Allerdings ist es üblich, alles vorhersehbare (wie eine Division durch 0), vorher aufzuhalten, damit solche Fehler erst gar nicht entstehen. Exceptions dienen dann mehr für "unvorhersehbare" Ereignisse oder wenn die Fehlerbehandlung an einem anderen Ort geschehen soll.


//Edit: Fehlerhaften Code korrigiert.
31.08.2009
Shelling 356 1 3
1
und wenn aufDemHeap nicht nur im Fehlerfall, sondern immer gelöscht werden soll, dann sollte es raus dem catch-Block
VfBernd 31.08.2009
Natürlich, dass hatte übersehen, danke für die Ergänzung. Jetzt, ausgeschlafen, muss ich auch eingestehen, dass mein Codebeispiel etwas Suboptimal ist, ich häng nochmal ein 2. an.
Shelling 31.08.2009
Viel erschreckender find ich allerdings auch noch, dass selbst wenn der Fehler geworfen wird, das Ergebnis ausgegeben wird. Den Fehler hab ich auch noch eben berichtigt. Dann sollte der Code soweit sauber sein, oder fällt euch noch was auf?
Shelling 31.08.2009
3
Bei der Antwort von Shelling rollen sich mir ja beinahe die Fußnägel hoch. Die ist so nicht skalier-/ und wartbar.

Eine bessere Lösung wäre, das RAII-Prinzip zu nutzen. Das geht zum Beispiel mit dem Shared Pointer von boost.

Der Code sähe dann in etwa so aus:

boost::shared_ptr<MeinObject> aufDemHeap(new MeinObject("abc"));
int x = a / b;
aufDemHeap->TueIrgendwas();



Das Objekt wird dann automatisch gelöscht, sobald der Block verlassen wird. Bei einer Division durch 0 sieht's aber sowieso ziemlich übel aus. Sinnvoller ist das Ganze bei C++ - Exceptions.

Gruß,

Andre

EDIT: Der Boost Shared Pointer ist nur ein Beispiel. Den mehrfach hier erwähnten std::auto_ptr kann man natürlich leichter benutzen (man muss keine Bibliothek einbinden). Eine weitere Möglichkeit besteht übrigens darin, eigene Klassen zu definieren, die im Konstruktor das new und im Destruktor das delete machen.
07.09.2009
andre 61 1 2
andre 61 1 2
Noch einfacher ist es einfach den von C++ in der STL bereitgestellten auto_ptr<> zu verwenden:

{
std::auto_ptr<MeinObject> aufDemHeap(new MeinObject("abc"));
...
...
} // hier wird der Destruktor von auto_ptr<> aufgerufen

// falls eine Exception auftritt werden die Objekte auf dem Stack ebenfalls ordentlich abgebaut
Frank 07.09.2009
Ah, boost::shared_ptr und std::auto_ptr kannte ich bisher noch gar nicht. Vielen Dank dafür, so ist die Lösung natürlich weit besser.
Shelling 08.09.2009
2
andre's Antwort ist im Prinzip richtig, es geht aber auch ohne eine zusätzliche Library wie Boost (die aber natürlich dennoch empfehlenswert ist...), es gibt in der normalen C++-Standard-Template-Library dafür das Klassentemplate auto_ptr:

#include <memory>

...

std::auto_ptr<MeinObject> aufDemHeap(new MeinObject("blub"));
int x = a / b;
aufDemHeap->machWas();
07.09.2009
mike 61 1 1
0
Ein Problem ensteht bei den harten Exceptions sowieso. Seit dem Visual Compiler 2005 landet man nicht unbedingt im catch block sondern das Programm wird beendet.

Ich stimme meinen Vorrednern zu das man solche Problem am besten gar auftreten lassen sollte. Ist wie im Handwerk wenn ich ein Brett zu kurz gesägt habe ist es zu kurz und so weit sollte man es gar nicht erst kommen lassen.
07.09.2009
AngelM 61 2
-1
MeinObject* aufDemHeap = new MeinObject("abc");
if ( b == 0 )
std::cout << "division durch 0!\n"
else
int x = a / b;
delete aufDemHeap;
07.09.2009
psychoschlumpf 77 1 2

Stelle deine Cplusplus-Frage jetzt!