Was passiert, wenn ich Speicher nicht freigebe?



  • Artchi schrieb:

    Oder einen Smartpoint std::auto_ptrstd::string.

    Meinst du nicht, daß DAS etwas übertrieben ist?



  • Ich muß zugeben, das ich das selten SO mache. Meistens gebe ich einfach std::wstring zurück und gut ist.

    Aber, der auto_ptr kostet ja praktisch nichts. Würde allerdings das Copy-on-Write-Pattern (CoW) bei basic_string eine Implementierungspflicht sein, würde ich mir den Smartptr bei Strings IMMER sparen. Denn dann wäre basic_string ja praktisch selbst eine Art Smartptr. CoW soll ja so in etwas das Konzept sein...

    std::auto_ptrstd::string habe ich aber tatsächlich schon an zwei drei Stellen in meinen realen Projekten. Da wo ich weiß, das die Strings seeeehr groß sein können, und CoW nicht garantiert ist. Aber mein Posting von ebend war auch eher provokativ gemeint. 😉



  • @Artchi: wie stellst du dir vor dass eine Standardkonforme Implementierung von std::basic_string mit COW aussehen soll? Was machst du wenn sich jmd. ne non-const Reference auf einen char/wchar_t z.B. über den operator [] holt...?
    Willst du den String dann gleich kopieren?

    Es gibt da zumindest einige Papers drüber warum std::basic_string mit COW nix bringt ODER eben nicht Standardkonform ist.

    BTW: COW + Multithreading = Langsam
    (interlocked instructions sind nicht gerade schnell)



  • Danke für die Aufklärung. Hab halt nur gedacht, das es CoW nur schwer zu implementieren ist. Und es deshalb nicht in jeder Implementierung drin ist. Wenn es auch andere Gründe gibt, dann ist das ja schon mal ein Hinweis.

    Aber dann ist es doch erst Recht nicht falsch, wenn ich std::auto_ptrstd::string als Rückgabewert definiere?



  • hustbaer schrieb:

    @Artchi: wie stellst du dir vor dass eine Standardkonforme Implementierung von std::basic_string mit COW aussehen soll? Was machst du wenn sich jmd. ne non-const Reference auf einen char/wchar_t z.B. über den operator [] holt...?
    Willst du den String dann gleich kopieren?

    Genau. Die Formulierung im Standard kann da keine Zweifel lassen. Im Übrigen sind nur nicht-konstante Referenzen (Zeiger, Iteratoren) problematisch.



  • Artchi schrieb:

    Aber dann ist es doch erst Recht nicht falsch, wenn ich std::auto_ptrstd::string als Rückgabewert definiere?

    Natürlich nicht, hab ich nie behauptet 🙂
    BTW: du kannst auch boost::shared_ptr<std::string const> verwenden, dann hast du fast sowas wie einen COW String. Bloss halt wieder das dumme "interlocked ist langsam" Problem -- unter dem leiden aber alle thread safe COW Implementierungen die ich so kenne.

    camper schrieb:

    Im Übrigen sind nur nicht-konstante Referenzen (Zeiger, Iteratoren) problematisch.

    Problematisch ist dass der operator [], und die Iteratoren (beim Dereferenzieren), eine Referenz zurückliefern müssen. Dürften sie einen Proxy zurückgeben wäre es nicht so ein Problem, der Proxy hätte dann einen operator = definiert welcher eben den String vor dem modifizieren kopiert.



  • hustbaer schrieb:

    Artchi schrieb:

    Aber dann ist es doch erst Recht nicht falsch, wenn ich std::auto_ptrstd::string als Rückgabewert definiere?

    Natürlich nicht, hab ich nie behauptet 🙂
    BTW: du kannst auch boost::shared_ptr<std::string const> verwenden, dann hast du fast sowas wie einen COW String. Bloss halt wieder das dumme "interlocked ist langsam" Problem -- unter dem leiden aber alle thread safe COW Implementierungen die ich so kenne.

    camper schrieb:

    Im Übrigen sind nur nicht-konstante Referenzen (Zeiger, Iteratoren) problematisch.

    Problematisch ist dass der operator [], und die Iteratoren (beim Dereferenzieren), eine Referenz zurückliefern müssen. Dürften sie einen Proxy zurückgeben wäre es nicht so ein Problem, der Proxy hätte dann einen operator = definiert welcher eben den String vor dem modifizieren kopiert.

    Hätte... der Standard nicht extra COW-Implementationen ermöglicht, hätten wir auch kein Problem... und das erscheint mir die günstigere Lösung - das ist zudem etwas, was man noch ändern kann ohne damit existierenden Code (abgesehen von der Standardbibliothek selbst) kaputt zu machen. Es gibt gute Gründe dafür, dass der Standard fast nie mit Proxies arbeitet.



  • OK danke.

    Ich werde dann wohl keine strings mehr von Funktionen zurückgeben lassem.
    Ist mir zu kompliziert. 🙄



  • Also gut, da stimm ich obba zu. Sehr kompliziert...
    Zumindest sagen mir die Begriffe da nix.

    Egal.

    Jedenfalls war dies mein Anfangskonzept (Man bedenke, ich bin Anfänger):

    template<class X>
    char* getbinary(const X &data)
    {
        X bit = 1;
        char *c = new char[8*sizeof(X)]+1;
        register char i;
    
        for(i = 8*sizeof(X) - 1; i >= 0; --i)
        {
            c[i] = (data & bit)? '1':'0';
            bit = bit << 1;
        }
        c[8*sizeof(X)] = 0;
    
        return c;
    }
    

    Ich arbeite nämlich grad ein Buch durch, bei dem <string> erst jetzt, also fast am Schluss drankommt...
    Ich werd das mit String lösen, denke ich.
    Oder ich lern was das Zeug bedeutet, was ihr da labert. 😉

    Ach ja @Artchi:
    Da hast du wohl Recht mit dem schlechten Design 😃



  • P.S.:

    Kritik stark erwünscht.

    (Und sorry wegen dem Doublepost)



  • Dieser Thread wurde von Moderator/in evilissimo aus dem Forum C++ in das Forum Rund um die Programmierung verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • ne0r schrieb:

    Kritik stark erwünscht.

    Also für einen Anfänger sieht das doch gar nicht schlecht aus (abgesehen davon, daß das "+1" an der falschen Stelle steht - und ich die Array-Größe vermutlich als Konstante festgelegt hätte).

    PS: Was hast du denn für ein Buch? In meinem stand "register" ziemlich weit hinten unter "was es noch gibt" 😉



  • thordk schrieb:

    "Was passiert, wenn ich Speicher nicht freigebe?"

    nichts. du ballerst nur dem ram voll und bekommst den nicht mehr leer, ohne dein programm zu beenden.

    Und es werden keine Destruktoren aufgerufen, was zu deutlich unangenehmeren Folgen führen kann.



  • Also das Buch, mit dem ich arbeite, ist Herbert Schildts "C++ die professionelle Referenz", da stehen Register ganz am Anfang unter nach dem Überblick über C, da werden alle diese Bezeichner eingeführt 😉 (const, volatile, register, static, etc.)

    Naja, das +1 macht da schon Sinn und dass die Array-Größe variabel ist, das hab ich mir schon überlegt 😉
    Die +1 muss sein, weil ich eine Zelle für jedes bit in data im Array haben will, plus eine Nullterminierung.
    Ok, man hätte sich auch einfach das größtmögliche Array raussuchen können, also das von long int und das wäre dann schon gegangen.



  • ne0r schrieb:

    Naja, das +1 macht da schon Sinn und dass die Array-Größe variabel ist, das hab ich mir schon überlegt 😉

    Ja, die +1 muß sein, aber sie gehört VOR die schließende Klammer ].



  • CStoll schrieb:

    ne0r schrieb:

    Naja, das +1 macht da schon Sinn und dass die Array-Größe variabel ist, das hab ich mir schon überlegt 😉

    Ja, die +1 muß sein, aber sie gehört VOR die schließende Klammer ].

    Ups, stimmt!
    😉



  • Artchi schrieb:

    ne0r! Die Frage ist eher, warum man einen nackten C-String zurück geben sollte? Wenn man was mit C-Strings machen will/muß, dann würde ich doch eher einen initialisierten char-Pointer als Parameter haben wollen:

    void return_a_cstring(char *str, std::size_t length);
    

    Dein Beispiel würde ich eher unter "schlechtes Design" einordnen.
    Und wenn ich C++ mache, würde ich dann sogar eher einen std::string oder std::wstring zurück geben. Dann muß sich niemand um die Freigabe kümmern. Oder einen Smartpoint std::auto_ptrstd::string.

    std::auto_ptr<std::string> return_a_string()
    {
        std::auto_ptr<std::string> str(new std::string());
        /* irgendwas in str schreiben */
        return str;
    }
    

    Nur eine Bemerkung/Frage am Rande: Da verlaesst du dich aber auch darauf, dass dein Compiler eine NRV Optimierung beherrscht, oder seh ich das falsch? Denn sonst koennte der Compiler ja (und AFAIK waere das auch voellig legal) den Destruktor von str gleich am Ende der Funktion aufrufen, und damit waere auch dein String futsch 😕 Schreibst du also ernsthaft solchen Code oder war das nur ein Fluechtigkeitsfehler?



  • Um ganz ehrlich zu sein, weiß ich nicht, was du meinst? 😕 Was soll NRV sein? Ich denke bei dem Konstrukt an gar keine Optimierung sondern daran, was logisch passiert. Aber ich weiß nicht worauf du hinaus willst.



  • Artchi schrieb:

    Um ganz ehrlich zu sein, weiß ich nicht, was du meinst? 😕 Was soll NRV sein? Ich denke bei dem Konstrukt an gar keine Optimierung sondern daran, was logisch passiert. Aber ich weiß nicht worauf du hinaus willst.

    NRV: Named Return Value Optimization
    http://fara.cs.uni-potsdam.de/~kaufmann/?page=GenCppFaqs&faq=Optimize#Answ

    Ich will auf folgendes hinaus:
    Du erstellst in der Funktion einen LOKALEN auto_ptr. Beim Verlassen der Funktion wird dieser auto_ptr deshalb (zumindest ohne NRVO) geloescht, und beim Loeschen wird ja dann auch der Dtor von auto_ptr aufgerufen. Und dabei wird dann ja auch dein String wieder geloescht. Oder?



  • Nee. So wie es im Code steht, wird eine Kopie des lokalen auto_ptr zurueckgegeben und keine "weak reference".


Anmelden zum Antworten