Exception und Dynamischer Speicher?
-
Hallo,
Folgendes ich fordere Speicher im Konstruktor meiner Klasse mittels new an! Da new eine Exception werfen kann, fange ich sie ab und gib den speicher frei der richtig angefoderte wurde.
Hier der mein Beispielcode:
#include<new> testclass::testclass() { try { testarray_[0] = new Class1(*this); } catch(std::bad_alloc &e) { cout<<"No Memory"<<endl; } try { testarray_[1] = new Class2(*this); } catch(std::bad_alloc &e) { delete testarray_[0] cout<<"No Memory"<<endl; } }Da dieses Array etwas länger ist wird der Code dementsprächend länger! Jetzt zu meiner eigentlichen Frage kann man es irgendwie verkürzen?
Und was passiert, wenn ich delete [] ausführe auf einen Speicher, der nicht angefodert werden konnte?mfg
-
Und was passiert, wenn ich delete [] ausführe auf einen Speicher, der nicht angefodert werden konnte?
Nichts.
Von daher kannst du so abkürzen:
#include<new> testclass::testclass() { for(int i=0; i<arraySize; ++i) testarrray_[i] = 0; try { testarray_[0] = new Class1(*this); testarray_[1] = new Class2(*this); } catch(std::bad_alloc &e) { delete testarray_[0] delete testarray_[1] // oder noch kürzer: // for(int i=0; i<arraySize; ++i) delete testarray_[i]; cout<<"No Memory"<<endl; } }#edit:
Ok, grade gelesen: delete auf einen NULL Pointer hat keine Auswirkung. Also vorher das ganze Array mit 0 initialisieren dann sollte es passen.
-
Und was passiert, wenn ich delete [] ausführe auf einen Speicher, der nicht angefodert werden konnte?
Wie soll das aussehen?
blub² schrieb:
Nichts.
Von daher kannst du so abkürzen:
...vorausgesetzt, testarray_ wurde zuvor initialisiert.
testclass::testclass() : testarray_() { try { testarray_[0] = new Class1(*this); testarray_[1] = new Class2(*this); ...zweckmäßiger sind hier allemal smartpointer.
-
Dan sollte das gesamte Array auf 0 gesetzt werden, da sonst jegliche Werte drin stehen können und dann hast du UB (wahrscheinlich Absturz)
Wenn du jetzt aber die Zeiger anstatt roh mit einem Smart Pointer verwaltest, dann musst du dich nicht einmal um das ganze kümmern, da es dann automatisch richtig freigegeben wird.
-
ok danke, dann werd ich es mit 0 initalisieren!
-
Das allein ist nicht exceptionsicher, du musst natürlich noch alles freigeben.
class MyClass { private: A* a[3]; public: MyClass() : a() { try { a[0] = new A(...); a[1] = new A(...); a[2] = new A(...); } catch (std::bad_alloc&) { for (int i = 0; i < 3; ++i) delete a[i]; throw; } } };Recht viel Code eigentlich. Mit dem Smart-Pointer
boost::scoped_ptrgeht das viel eleganter, der Konstruktor reduziert sich auf die Speicheranforderung.class MyClass { private: boost::scoped_ptr<A> a[3]; public: MyClass() // keine explizite Initialisierung des Arrays nötig { a[0].reset(new A(...)); a[1].reset(new A(...)); a[2].reset(new A(...)); // kein try-catch mehr nötig, keine deletes mehr nötig, // alles wird automatisch freigegeben! // Die Exception fliegt auch von selbst weiter. } };Übrigens brauchst du dich im Allgemeinen nicht um
std::bad_alloczu sorgen, da diese Exception recht selten geworfen wird - und dann meistens, weil zu viel Speicher (oder ein zu grosser Block) angefordert wurde. Viel häufiger trifft man den Fall an, bei dem ein Konstruktor eine Exception wirft und somit einnewfehlschlägt. In meiner oberencatch-Abfrage sind solche Exceptions allerdings nicht inbegriffen.