Invalid pointer



  • Hallo zusammen,

    ich verzweifle an einen "Invalid pointer". Ich habe mir folgende Klassenhierarchie gebastelt:

    Meine Basisklasse:

    template<typename P >
    class treeitem {
    	public:
    		P * getParent() {
    			return _parent;
    		}
    
    		void setParent(P * parent) {
    			_parent = parent;
    		}
    	protected:
    		P * _parent;
    };
    

    Davon abgeleitet habe ich

    class Node: public treeitem<Node> {
    	public:
    		typedef std::vector<treeitem<Node> *>::iterator Iterator;
    
    		Node();
    		virtual ~Node();
    		Iterator begin();
    		Iterator end();
    
    	private:
    		std::vector<treeitem<Node> *> children;
    };
    

    und

    class Leaf : public treeitem<Node> {
    	public:
    		Leaf();
    		virtual ~Leaf();
    };
    

    Der Destructor von Node sieht so aus:

    Node::~Node() {
    	Node::Iterator it = children.begin();
    	while (it != children.end()) {
    		treeitem<Node> * child = *it;
    		if (child != NULL) {
    			delete child;
    		}
    		++it;
    	}
    }
    

    Den Invalid pointer bekomme ich immer dann, wenn in Zeile 6 des Destructors

    delete child;
    

    aufgerufen wird.

    Was laeuft das schief?

    Danke fuer eure Hilfe.



  • sunnyholland schrieb:

    Den Invalid pointer bekomme ich immer dann, wenn in Zeile 6 des Destructors

    delete child;
    

    aufgerufen wird.

    Was laeuft das schief?

    Vielleicht hast du vorher einen invaliden Pointer eingefügt?



  • Im Debugger sieht alles ganz normal aus.

    Meine Testroutine sieht so aus:

    Node * node = new Node();
    Leaf * leaf = new Leaf();
    leaf->setParent(node);
    *(node->begin()) = leaf;
    delete node;
    


  • Gibt begin() einfach children.begin() zurück oder steckt da mehr Logik drin? children.begin() ist beim leeren Vector ja == children.end() und Du füllst an dieser Speicherstelle einfach was rein. Schätze, das gibt undefiniertes Verhalten.

    Jedenfalls solltest Du in den vector via push_back einfügen. Eigentlich hat das mit deinem Fehler aber nicht direkt etwas zu tun.



  • sunnyholland schrieb:

    Im Debugger sieht alles ganz normal aus.

    Meine Testroutine sieht so aus:

    Node * node = new Node();
    Leaf * leaf = new Leaf();
    leaf->setParent(node);
    *(node->begin()) = leaf;
    delete node;
    

    D.h. du weist children.begin() einfach einen Wert zu, ohne den Vector entsprechend zu vergössern? Das geht nicht, einfügen geht mit push_back().



  • Ich hatte vorher einfach eine Array

    treeitem<Node> * children[8];
    

    definiert und mir einen Iterator dazu geschrieben. Da passierte das selbe. Denn Array habe ich dann durch einen std::vector ersetzt und im den Konstruktor von Node folgender massen ergaenzt:

    Node::Node() 
        : children(8) 
    {
    }
    

    Lasse ich mir dann die Groesse des Vectors mittel size() ausgeben, erhalte ich als Antwort 8.

    Ich habe mir die Pointer nocheinmal genau angesehen und festgestellt, dass die Adresse von Leaf nach "new Leaf()" 0x81d098 ist, abgelegt im Vector wird aber 0x81d098. Damit ist der invalid pointer beim delete erklaert, nicht jedoch, warum das Element im Vector auf eine andere Adresse zeigt.



  • Wenn ich mein Template treeitem durch eine konkrete Klasse ersetze, geht es. Aber warum?


  • Mod

    Dir wurden bereits mehrere Fehler genannt. Ein weiterer ist, dass du deine Leaf über Basisklassenpointer löscht, ohne dass die Basisklasse einen virtuellen Destruktor hat.

    dass die Adresse von Leaf nach "new Leaf()" 0x81d098 ist, abgelegt im Vector wird aber 0x81d098

    😕



  • Dem Template fehlt auf jeden Fall ein virtueller Destruktor. Das könnte es sein.



  • So einfach!!! Das wars. Vielen Dank!!



  • Deine Klasse wird auch robuster, wenn du im Konstruktor des treeitem Parent mit 0 initialisierst.


Anmelden zum Antworten