Wie Speicher elegant wieder freigeben (bei Funktionsabbruch)?
-
Hallo,
ich habe mehrere Funktionen, die hintereinander ausgeführt werden sollen. Falls eine dieser Funktionen fehlschlägt soll die Funktion nicht weiter ausgeführt werden, initialisierter Speicher aber freigegeben werden. Bisher sieht mein Konstrukt so aus:
Aufruf()
{
reserviere Speicher1
reserviere Speicher2if(!Funktion1(Speicher1, Speicher2)) {gebe Speicher1 frei; gebe Speicher2 frei; return false;}
if(!Funktion2(Speicher1, Speicher2)) {gebe Speicher1 frei; gebe Speicher2 frei; return false;}
if(!Funktion3(Speicher1, Speicher2)) {gebe Speicher1 frei; gebe Speicher2 frei; return false;}
Hier kommt weiterer Code der nur ausgeführt werden soll, wenn alles vorher geklappt hat.
gebe Speicher1 frei;
gebe Speicher2 frei;return true;
}Ich finde die Lösung nicht sehr elegant, da der selbe Code mehrfach vorhanden ist. Eine Verschachtelung mit if()s finde ich allerdings noch störender. Eine weiter Möglichkeit wäre ein success-flag. Dann müsste vor jeder Funktion geprüft werden, ob der Code bisher erfolgreich (successful) war. Man könnte auch eine Funktion schreiben, die den Speicher freigibt und vor dem Return ausgeführt wird.
Wie würdet ihr das implementieren?
Vielen Dank für eure Hilfe!
Moritz
-
RAII
-
std::tr1::scoped_ptr
boost::scoped_ptr
std::auto_ptr
, je nachdem was zur Verfügung steht.
-
Wozu musst du den Speicher überhaupt dynamisch anfordern? Zeig mal ein konkretes Besipiel wozu du
reserviere Speicher1 reserviere Speicher2
brauchst.
-
brotbernd schrieb:
Wozu musst du den Speicher überhaupt dynamisch anfordern? Zeig mal ein konkretes Besipiel wozu du
reserviere Speicher1 reserviere Speicher2
brauchst.
Also es handelt sich dabei um Bilder. Ich bekomme (habe ich oben weggelassen) Farbbilder übergeben die ich dann in Schwarzweiß-Bilder konvertieren muss. Ich benutze OpenCV und muss daher mit cvCreateImage Speicher reservieren.
Das sieht ungefähr so aus:
IplImage* imageBW1 = cvCreateImage ( imgSize, IPL_DEPTH_32F, 1 );
IplImage* imageBW2 = cvCreateImage ( imgSize, IPL_DEPTH_32F, 1 );Leider weiß ich nicht was RAll bedeuten soll und das:
# std::tr1::scoped_ptr
# boost::scoped_ptr
# std::auto_ptr
habe ich noch nie gesehen...Der Speicher wird mit cvReleaseImage wieder freigegeben.
Moritz
-
Moritz06 schrieb:
Leider weiß ich nicht was RAll bedeuten soll und das:
# std::tr1::scoped_ptr
# boost::scoped_ptr
# std::auto_ptr
habe ich noch nie gesehen...Kennst du Suchmaschinen? Oder vielleich Wikipedia?
-
Don't bite my head off.
Das Problem ist, dass ich gelesen haben, dass ich den Speicher nicht mit delete freigeben kann.
The cvCreate* return a pointer wich corresponds to what would happen
using new. but you cannot use delete or free, you must use cvRelease*
to clean up.http://tech.groups.yahoo.com/group/OpenCV/message/56349
Es tut mir leid, das hätte ich oben sagen sollen. Es war mir aber auch nicht so bewusst.
-
In RAII Manier macht man sowas entweder etwa so
class Image { public Image(a, b, c) :img_(CreateImage(a,b,c)) {} ~Image() { try{ReleaseImage(img_);} catch(...){} } // Access to Image... private: IplImage* img_; };
oder mit einer generischen Lösung wie
scoped_ptr
o.ä. Denen muss man dann nur sagen, dassReleaseImage
stattdelete
benutzt werden muss.
-
Moritz06 schrieb:
Das Problem ist, dass ich gelesen haben, dass ich den Speicher nicht mit delete freigeben kann.
Kein Problem, das ist kein Argument gegen RAII. Schau's dir mal an:
http://de.wikipedia.org/wiki/RAII
Du kannst dir einfach eine kleine Klasse bauen, die im Destruktor cvRelease ausführt.
-
Ah ok, viele Dank. Das werde ich ausprobieren.
-
OpenCV hat (spätestens seit V2.1) auch ein C++-Interface, da brauchst du dich dann gar nicht mehr um den Speicher kümmern!
cv::Mat img1 = cv::imread("bild.jpg"); // oder so ähnlich
Kann ich nur empfehlen, geht alles viel einfacher damit
-
Tachyon schrieb:
std::tr1::scoped_ptr
Gibts leider nicht, was ich immer noch nicht nachvollziehen kann. Ich wäre schon ein paar Male um
scoped_ptr
im TR1 froh gewesen.