Zuweisungsoperatorüberladung -> uninizialisierte Zeiger



  • Hallo an Alle,

    ich bin noch recht neu in der ganzen C++ Welt, habe sonst viel mit C# und ein wenig mit C gemacht, also bitte ich darum meine (höchst wahrscheinlich) Noobige Frage zu entschuldigen 🙂

    Und zwar habe ich eine Klasse A die eine private Member vom Typ char * hat. Dieser wird im Konstruktor mit NULL bzw. 0 initialisiert. Außerdem ist der Kopierkonstruktor und die operator= Methode implementiert.
    Dann habe ich eine Klasse B mit einem privaten Member vom Typ A. Dem Konstruktor muss A übergeben werden, folglich wird die operator= Methode von A aufgerufen.
    Das Problem ist, dass in dieser Methode auf der Source Seite die Zeiger nicht initialisiert sind und auf irgendwas zeigen. Wird in A Speicher für char * reserviert, tritt das Problem nicht auf.

    Hier mal der Source-Code dazu. Die Anwendung crasht beim delete. Aber eigentlich dürfte delete nie aufgerufen werden, weil die Zeiger ja NULL sein müssten.
    Kompiliert hab ich es unter Linux mit g++;

    #include <string.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    class A {
    private:
        char *key;
        size_t key_size;
    public:
        A() {
            key = NULL;
            key_size = 0;
        }
        A(const A& src) {
            if(src.key != NULL)
            {
                this->key = new char[src.key_size];
                memcpy(this->key, src.key, src.key_size);
                this->key_size = src.key_size;
            }
        }
        ~A() {
            // this->key sollte NULL sein ist es aber nicht, warum auch immer
            if(this->key != NULL)
                delete this->key;
        }
        A &operator = (const A &src) {
            if(this != &src)
            {
                // src.key sollte NULL sein ist es aber nicht, warum auch immer
                if(src.key != NULL)
                {
                    this->key = new char[src.key_size];
                    memcpy(this->key, src.key, src.key_size);
                    this->key_size = src.key_size;
                }
            }
        }
    };
    
    class B {
    private:
        A a;
    public:
        B(A a) {
            this->a = a;
        }
    };
    
    int main(int argc, char** argv) {
    
        A a;
        B *b = new B(a);
        delete b;
        return 0;
    }
    

    Schon mal vielen Dank für eure Mühen und die Aufklärung des Sachverhalts.



  • nanohcv schrieb:

    A(const A& src) {
            if(src.key != NULL)
            {
                this->key = new char[src.key_size];
                memcpy(this->key, src.key, src.key_size);
                this->key_size = src.key_size;
            }
        }
    

    Überleg mal was in deinem Copy-Constructor passiert wenn src.key NULL ist. Wie wird dann key und key_size von dem neuen Objekt initialisiert?

    PS: Ein Check auf ungleich NULL beim delete ist unnötig, da delete bei einem NULL Pointer gar nichts macht.



  • Ach ja, so einfach.
    Manchmal sieht man den Wald vor lauter Bäumen nicht.

    Besten Dank.



  • Wenn wir schon dabei sind: std::string statt diesem char-zeigergefuchtel und nimm die ollen c-header raus. Alles in der c-standardbibliothek, die teil der von c++ ist, solltest du mit einem c davor includen: string.h -> cstring etc. Generell gibt es aber keinen grund, diese einzubinden, außer vielleicht dinge wie cstdint.
    Soweit wie möglich auf allokationen mit new verzichten. Wenn, dann kommen smartpointer, zb unique_ptr, zum einsatz.


Log in to reply