Speicherproblem im Destruktor



  • Könnte jemand bitte den obigen Code testen und berichten ob der gleiche Fehler auftritt? Vielleicht liegt es ja doch an irgend einer Einstellung im Visual Studio.

    mfg



  • ChrisR schrieb:

    der Copy-Constructor (wenn ich einen einfüge) wird nie ausgeführt!

    Kannst du den Kopierkonstruktor mal posten?



  • bei mir wird der destruktor auch 2 mal aufgerufen
    und es kommt zum absturz....



  • Copy-Constructor:

    String(const String& s){
    }
    

    mfg



  • Vllt. solltest du den eher so schreiben (jetzt kopiert er den char-Vektor jedesmal):

    #include <cstring>
    
    class String{
      //...
      const char* raw() const {
        return c;
      }
    public:
      //...
      String(const String &s){
        c = new char[100];
        const char *str = s.raw();
        int len = std::strlen(str);
        std::strncpy(c, str, len);
      }
    };
    

    MfG

    GPC



  • GPC schrieb:

    Vllt. solltest du den eher so schreiben

    Dass meine Variante keinen Sinn macht ist mir klar. Aber nachdem er sowieso nie ausgeführt wird (habe durchdebuggt und eine Testausgabe gemacht) spielt das bei diesem Beispiel keine Rolle. Die Frage ist vielmehr wieso sich die Existenz des Copy-Constructors darauf auswirkt wie oft der Destruktor ausgeführt wird.

    mfg



  • steff3 schrieb:

    bei mir wird der destruktor auch 2 mal aufgerufen
    und es kommt zum absturz....

    Einmal wird das String() Objekt in main() zerstört und einmal das Objekt von SetString(String s)

    Der Fehler ist, dass 2 Objekte bestehen und beide den selben Speicher zulöschen versuchen. Du musst den char* im Copy-Ctor und bei op= kopieren..



  • [quote="Konrad"]

    steff3 schrieb:

    Der Fehler ist, dass 2 Objekte bestehen und beide den selben Speicher zulöschen versuchen. Du musst den char* im Copy-Ctor und bei op= kopieren..

    Das wäre auch meine erste Idee gewesen. Tatsache ist aber, dass der Copy-Construktor (selbst wenn ich ihn implementiere) nie aufgerufen wird (das hat mit der Debugger und eine Testausgabe bestätigt). Daher kann es keine Rolle spielen was darin gemacht wird.

    Warum der Copy-Construktor nie aufgerufen wird weiß ich auch nicht sicher. Meine Vermutung ist, dass das Objekt nicht zuerst erstellt und dann kopiert wird, sondern gleich von Anfang an am Stack der aufgerufenen Funktion erzeugt wird (wahrscheinlich eine Optimierung wenn man das String() direkt in den Aufruf schreibt). Jedoch dürfte dann der Destruktor nur 1 Mal laufen.

    mfg



  • Es werden zwei Objekte erzeugt, einmal auf dem Stack von setString und einmal in main. Das heisst es wird zweimal ein Constructor und zweimal der Destructor aufgerufen. Ich schreibe "ein Constructor", weil das entweder zweimal der Default Constructor oder einer davon der Default Construktor und der andere der Copy Constructor sein muss.

    Alles andere wäre eine grobe Panne in der Implementierung der Sprache 😉

    EDIT:

    Ich muss mich selbst korrigieren, der folgende Code:

    #include <iostream>
    using namespace std;
    
    class String {
    private:
      char* c;
    public:
      String()
      {
        cout << "ctor" << endl;
        c = new char[100];
      }
      String(const String& o)
      {
        cout << "copy ctor" << endl;
      }
      String& operator=(const String& o)
      {
        cout << "op=" << endl;
      }
      ~String()
      {
        cout << "dtor" << endl;
        delete[] c;
      }
    };
    
    void setString(String s)
    {
    }
    
    int main(void)
    {
      setString(String());
      return 0;
    }
    

    wird von meinem g++ soweit herunteroptimiert, dass tatsächlich nur einmal der Constructor durchlaufen wird. Allerdings gilt dasselbe für den Destructor, insofern könnte es sich bei Dir tatsächlich um eine Macke im Compiler handeln.

    Wenn ich mit String s; setString(s); ein Objekt erzeuge und übergebe wird korrekterweise Ctor, Copy Ctor, Dtor, Dtor ausgegeben...



  • So muesste es sein. Ist aber offensichtlich nicht der Fall. Bei mir (gcc) wird auch nicht kopiert und der d'tor wird nur einmal aufgerufen.



  • @Apollon: Besser als einmal Ctor, zweimal Dtor, das klingt irgendwie... FALSCH 😉



  • Ok, und wieso wird mein Destruktor nur noch 1 Mal aufgerufen, jetzt wo mein Copy-Constructor korrekt ist?

    mfg



  • ChrisR schrieb:

    Ok, und wieso wird mein Destruktor nur noch 1 Mal aufgerufen, jetzt wo mein Copy-Constructor korrekt ist?

    Das nennt sich Optimierung - der Compiler rationalisiert die temporäre Variable weg, die für den Aufruf von SetString() benötigt wird und initialisiert deren Parameter direkt mit dem Default-Ctor.

    (und da er nur ein Objekt erzeugt hat, benötigt er auch nur einen Dtor-Aufruf)


Anmelden zum Antworten