Wieso reicht delete[] zum Löschen von Arrays?



  • theta schrieb:

    🙄

    Jetzt mal nicht frech werden, junger Mann. 🙂



  • Wie mach ich denn das schlauer? Mit einem Container? Wenn ich einen will wende ich mich an Hanjin, und die sind mit über 5 Mrd. auch pleite gegangen:

    // keywords
    	KeyWordsData *keywords_data = new KeyWordsData;
    	if( keywords_data )
    	{
    		//keywords_data->fail_keywords = thePrefs.;
    		keywords_data->success_keywords = new CStringA( thePrefs.success_kw_edit_ascii );
    	}
    
    	// send new data to the thread
    	if( !::PostThreadMessage(threadID, UWM_SETTINGS_AND_KEYWORDS_DATA, (WPARAM)settings_data, (LPARAM)keywords_data) )
    	{ /* failed */
    		//TRACE(_T("Image Thread 0x%02x UWM_GET_HTTP/ALL task failed\n"), m_test_thread.threadID);
    		delete settings_data->proxy;
    		delete settings_data;
    
    		//delete keywords_data->fail_keywords;
    		delete keywords_data->success_keywords;
    		delete keywords_data;
    		return( false );
    	} /* failed */
    


  • Du kannst trotzdem ne Helperstruct entwerfen, ähnlich std::unique_ptr, der das ganze automatisch deleted. Das zu LPARAM etc zu casten ist zwar ziemlich genau undefiniertes verhalten, aber sollte funktionieren. Schließlich enthält dieses Object lediglich nen Zeiger auf die Daten.

    Ohne dieses casten täts auch eine Liste, wobei dann lediglich ein zeiger auf das Element mitgegeben wird, was dann beim Eintreffen wieder entfernt werden kann. Könnte bei C-Verehrern allerdings auf Naserümpfen aufgrund des 'Overheads' stoßen.



  • Techel schrieb:

    Du kannst trotzdem ne Helperstruct entwerfen, ähnlich std::unique_ptr, der das ganze automatisch deleted.

    Und wie? Das würde mich auch interessieren, hatte ziemlich das selbe Problem nämlich auch schon ein paar mal.

    std::unique_ptr deleted ja einfach im destruktor, also wenn er out of scope geht... das geht in dem Fall ja nicht.

    Techel schrieb:

    Das zu LPARAM etc zu casten ist zwar ziemlich genau undefiniertes verhalten, aber sollte funktionieren.

    Klingt nicht gerade zufriedenstellend...



  • Wenn PostThreadMessage scheitert ist die Vorgehensweise ja schon gezeigtt. Der Rest sollte klar sein. Delete passiert dann beim Empfänger.



  • EOP schrieb:

    Wenn PostThreadMessage scheitert ist die Vorgehensweise ja schon gezeigtt. Der Rest sollte klar sein.

    Wenn der Rest klar ist, warum fragst du dann "Wie mach ich denn das schlauer?" 😕

    Mir ist aber auch nicht klar wie ich das gezeigte mit einem smart-pointer realisieren kann, deswegen die Frage (wie ich es mit standard new/delete mache ist klar aber darum ging es ja nicht).



  • Bei den delete Anweisungen mit -> drinnen sollte wohl klar sein wie man sie los wird: unique_ptr als Member verwenden.
    Und bei den anderen beiden kann auch unique_ptr helfen: einfach statt "if Fehler -> delete" den Code zu "if Erfolg -> release" umbauen.



  • hustbaer schrieb:

    Bei den delete Anweisungen mit -> drinnen sollte wohl klar sein wie man sie los wird: unique_ptr als Member verwenden.
    Und bei den anderen beiden kann auch unique_ptr helfen: einfach statt "if Fehler -> delete" den Code zu "if Erfolg -> release" umbauen.

    Hm, release hab ich bis jetzt noch nie verwendet... scheint höchste Zeit zu werden 👍



  • c

    hustbaer schrieb:

    Bei den delete Anweisungen mit -> drinnen sollte wohl klar sein wie man sie los wird: unique_ptr als Member verwenden.
    Und bei den anderen beiden kann auch unique_ptr helfen: einfach statt "if Fehler -> delete" den Code zu "if Erfolg -> release" umbauen.

    Du meinst, das funktioniert auch in einem anderen thread.
    Sorry for hijacking this thread. Wäre eigentlich ein MFC-Thema.



  • SeppJ schrieb:

    Und falls du es nicht mitbekommen haben solltest: In C++ sollte es niemals vorkommen, dass du new/delete in Anwendungscode hast.

    wieso? Wenn ich mir einen Kugelschreiber kaufe, werfe ich deshalb doch auch nicht alle Bleistifte weg.



  • Dumpfbackenhausen


  • Mod

    zufallswert schrieb:

    SeppJ schrieb:

    Und falls du es nicht mitbekommen haben solltest: In C++ sollte es niemals vorkommen, dass du new/delete in Anwendungscode hast.

    wieso? Wenn ich mir einen Kugelschreiber kaufe, werfe ich deshalb doch auch nicht alle Bleistifte weg.

    😕 Besserer Vergleich wäre: Wenn du einen Füller hast, steckt du nicht deinen Finger in die Tinte und malst damit auf dem Papier herum.



  • EOP schrieb:

    c

    hustbaer schrieb:

    Bei den delete Anweisungen mit -> drinnen sollte wohl klar sein wie man sie los wird: unique_ptr als Member verwenden.
    Und bei den anderen beiden kann auch unique_ptr helfen: einfach statt "if Fehler -> delete" den Code zu "if Erfolg -> release" umbauen.

    Du meinst, das funktioniert auch in einem anderen thread.
    Sorry for hijacking this thread. Wäre eigentlich ein MFC-Thema.

    Ja klar funktioniert das auch in einem anderen Fred.
    Der unique_ptr macht ja im Endeffekt auch nix anderes als ein delete - nur halt automatisch, in dem Fall wenn das "äussere" Objekt welches den unique_ptr als Member hat gelöscht wird.
    Der einzige Unterschied ist da echt dass du das delete nicht mehr selbst hinschreiben musst.

    Nimm dir aber auch den anderen Teil zu Herzen. Also das Muster
    - Verpacken in Smart-Pointer von Anfang an
    - Alles fertig zusammenbauen
    - Übergabe irgendwohin, über einen Kanal wo man nicht direkt den Smart-Pointer transportieren kann
    - Smart-Pointer Release falls Übergabe funktioniert hat

    Das ist zwar auch nicht super-schön, weil man eben manuell mit release rumfummeln muss... aber IMO immer noch viel besser als im Fehlerfall selbst delete aufzurufen. Ownership sollte immer klar und automatisch geregelt sein, ab dem Zeitpunkt wo ein Objekt existiert. Also ab dem new oder woher auch immer man das Objekt bekommt. Wenn man dazwischen unschöne Kanäle wie PostMessage verwenden muss, dann geht's halt nicht anders (*), aber davor und danach immer
    Smart-Pointer.

    *: Natürlich geht es auch bei PostMessage anders. Beispielsweise indem man die Message irgendwo in ne Membervariable steckt (evtl. auch ne Liste/Queue falls nötig) und dann per PostMessage bloss noch die Benachrichtigung verschickt dass es was in der Membervariable/Queue abzuholen gibt. (**) Gibt aber natürlich Fälle wo sowas nicht geht bzw. nicht praktikabel ist. Und in diesen Fällen kann (und sollte) man die Bereiche wo man keinen automatischen "Resourcenhalter" hat immer noch so weit wie möglich minimieren.

    **: OK, das hat Techel ja schon vorgeschlagen.

    ps: Wozu überhaupt nen CStringA -Zeiger als Member und nicht direkt den CStringA ? Und... warum man besser "if erfolg -> release" statt "if fehler -> delete" macht, sollte dann auch klar sein: Weil beim new CStringA (siehe "alles fertig zusammenbauen" oben) ne Exception rausfliegen könnte. Was natürlich auch so bleibt wenn der CStringA direkt als Member drinnen steckt - der muss seinen Speicher beim Assignment ja auch irgendwoher nehmen.



  • Danke für die Antwort, hustbaer.
    Ich muss mir das aber noch mindestens einmal durchlesen.
    Im Moment hab ich sowieso nur VS 2005 zur Verfügung.



  • Bidde bidde.

    Naja, ob jetzt std::unique_ptr , boost::scoped_ptr oder boost::movelib::unique_ptr macht diesbezüglich keinen Unterschied, kannste alle drei nutzen - bzw. mit VS 2005 halt nur die letzten beiden.

    Und gegenüber manuellem delete wäre sogar std::auto_ptr ein Fortschritt. Wobei es natürlich kaum Sinn machen wird std::auto_ptr zu verwwenden wenn man auch die Boost verwenden kann.
    (Und wenn du keine Boost hast, dann ist so ne minimale scoped_ptr Implementierung auch keine Hexerei - das sind ein paar ziemlich unspannende Zeilen mit wenig Fehlerpotential.)



  • Ich habe eine Bekannte, deren Eltern sehr um die Sicherheit ihrer Tochter besorgt waren und sie auch entsprechend erzogen. Leider kann besagte Tochter nicht die Weihnachtskerzen mit Feuerzeug oder Streichhoelzer anzuenden, da sie ungeuebt und sehr aengstlich im Umgang mit Feuer ist. Das Dilemma von brauchbaren Dingen ist, dass sie im gleichen Sinne missbraucht werden koennen. Wenn sie unnuetzt waeren, so werden sie auch nicht missbraucht. Gleiches trifft fuer Messer, Gabel, Schere, Licht zu. Ich fuer meinen Teil bin schon erwachsen.

    Angst vor new/delete ist fehl am Platz, auch das dogmatische warnen. Dudududu, so nicht ... Leider spricht niemand ueber die Nachteile oder den Missbrauch von smart Pointern. Smart Pointer sind Implementationsdetail (siehe Stroustrup-Videos). Leider tendieren sie, uebermaessig intensiv benutzt zu werden, so dass dieses Detail nach aussen getragen wird, insbesondere bei std::shared_ptr zu beobachten. Wenn der ganze Code mit shared_ptr uebersaeht ist, dann hat man garantiert was falsch gemacht. Leider wird genau dieses Muster hier empfohlen. Ein Kollega meinte: We do not need smart pointer but we need smart developers. Ich wundere mich sowieso, wie wir zum Mond fliegen konnten ohne smart Pointer. Kaum etwas aus pre-C++11 ist ungueltig geworden.

    Wo werden von mir haupsaechlich rohe Zeiger benutzt: DLL-Grenzen. Z.B. Arrays werden als Zeiger + Anzahl der Elemente uebergeben. Alle Klassen meist durch Pimpl-Idiom gekapselt (roher Zeiger, kein unique_ptr). Auch der Verzicht auf Klassen der Laufzeitumgebung hat mir schon viel Aerger erspart, genauso wie virtual.

    Einige Kommentare:

    Die benötigte Array-Grösse, um die Elemente korrekt zerstören zu können liegt bei den Standard-Containern meist auf dem "heißen" Stack und damit sehr wahrscheinlich im CPU-Cache.

    loled really hard. delete von Elementen als Performanceargument ins Feld fuehren. Nein, das liegt nicht im kritischen Code.

    zu solchen "Tricks" greifen, wie die Größe des Arrays vor den Nutzdaten zu speichern

    Das ist kein schmutziger Trick sondern ein Implementationsdetail. Auch https://www.youtube.com/watch?v=vElZc6zSIXM sind keine schmutzigen Tricks, sie wissen nur, wie mit dem Messer, Gabel, Schere, Licht umzugehen ist. Ach, schaue bitte nicht in die Sourcen der C++-Standardbibliothek, alles schmutzige Tricks ... 🙂

    Wie mach ich denn das schlauer?

    OMG ... Benutze nicht die Messagequeue des Fensters. Weil ... reasons ...

    You'll end up with a unresponsive GUI. Our company has a lot of experience with exactly this failed designed technique

    Quelle: http://stackoverflow.com/questions/123323/how-deep-is-the-win32-message-queue

    auto_ptr

    Das wird seit jeher totgeschwiegen, genauso wie vector<bool>.



  • knivil schrieb:

    Angst vor new/delete ist fehl am Platz, auch das dogmatische warnen.

    Falsch und falsch.

    knivil schrieb:

    Dudududu, so nicht ... Leider spricht niemand ueber die Nachteile oder den Missbrauch von smart Pointern.

    Doch, eigentlich recht viele Leute. Unter anderem du jetzt - bloss leider nicht sachlich.

    Und auf den Rest im Detail einzugehen ist mir ehrlich gesagt zu doof.



  • Smart Pointer sind Implementationsdetail (siehe Stroustrup-Videos). Leider tendieren sie, uebermaessig intensiv benutzt zu werden, so dass dieses Detail nach aussen getragen wird, insbesondere bei std::shared_ptr zu beobachten.

    Beachte, dass ein Smart Pointer ohne spezialisierten Deleter-Vorgang kein Implementationsdetail zum Vorschein bringt.

    Das ist nämlich das, was die meisten brauchen.

    Ist auch viel sicherer gerüstet gegen Fehler usw. Scope raus -> Freigeben.



  • hustbaer schrieb:

    knivil schrieb:

    Angst vor new/delete ist fehl am Platz, auch das dogmatische warnen.

    Falsch und falsch.

    knivil schrieb:

    Dudududu, so nicht ... Leider spricht niemand ueber die Nachteile oder den Missbrauch von smart Pointern.

    Doch, eigentlich recht viele Leute. Unter anderem du jetzt - bloss leider nicht sachlich.

    Und auf den Rest im Detail einzugehen ist mir ehrlich gesagt zu doof.

    Ich weiss, wer argumentiert, hat verloren. Du hast gewonnen.

    Ist auch viel sicherer gerüstet gegen Fehler usw. Scope raus -> Freigeben.

    Ich habe explizit shared_ptr angefuehrt.



  • knivil schrieb:

    Ich habe explizit shared_ptr angefuehrt.

    Wenn du keinen Reference counting brauchst, brauchst du den auch nicht.


Anmelden zum Antworten