2016-03-25 3 views
2

Ich habe ein Problem mit Polymorphismus in einem C++ - Projekt, an dem ich arbeite. Ich habe eine Basisklasse mit dem Namen State, und eine abgeleitete TestState Klasse. Ich versuche, eine virtuelle Funktion aufzurufen, die in der abgeleiteten Klasse von einem State Zeiger überschrieben wird. Die virtuelle Funktion aufgerufen wird, aber beim Löschen des Zeigers ich die folgende Fehlermeldung erhalten:Ungültige Adresse für RtlValidateHeap beim Löschen des Zeigers auf abgeleitete Klasse

Invalid address specified to RtlValidateHeap(00FF0000, 0018FD74) 

Nach anderen Antworten sucht Ich habe in der Lage zu verstehen, dass dies bedeutet, dass der Heap beschädigt ist, aber keine der Lösungen Ich habe gefunden, dass ich für mich gearbeitet habe.

Dies ist der Code, den ich laufen:

int main() 
{ 
    TestState test; 

    State *state = new State(); 
    state = &test; 

    state->Init(); 

    delete state; 
} 

State.h

#pragma once 

#include <iostream> 

class State 
{ 
public: 
    State(); 
    virtual ~State(); 

    virtual void Init(); 
    virtual void Reinit(); 
    virtual void Deinit(); 
}; 

State.cpp

#include "State.h" 

State::State() 
{ 
} 

State::~State() 
{ 
    std::cout << "Destroying State!" << std::endl; 
} 

void State::Init() 
{ 
    std::cout << "Initialized State!" << std::endl; 
} 

void State::Deinit() 
{ 
} 

void State::Reinit() 
{ 
} 

TestState.h

#pragma once 
#include "State.h" 
#include <iostream> 

class TestState : public State 
{ 
public: 
    TestState(); 
    ~TestState(); 

    void Init(); 
    void Deinit(); 
    void Reinit(); 
}; 

TestState.cpp

#include "TestState.h" 

TestState::TestState() 
{ 
} 

TestState::~TestState() 
{ 
    std::cout << "Destroying TestState!" << std::endl; 
} 

void TestState::Init() 
{ 
    std::cout << "Initialized TestState!" << std::endl; 
} 

void TestState::Deinit() 
{ 
} 

void TestState::Reinit() 
{ 
} 

Der Destruktor von sowohl Staat und Teststate wird aufgerufen, wenn der Zeiger gelöscht wird.

Vielen Dank im Voraus.

+0

Sie vermissen Copy/Move Konstruktoren/Zuweisungsoperatoren! – o11c

+0

Entschuldigung, ich bin neu in C++, kannst du erklären, warum ich sie in diesem Fall brauchen würde? – Dramentiaras

+0

Es heißt die "Regel von 3" oder "Regel von 5". Wenn Sie * an * des Konstruktors destruktor, copy/move, Zuweisungsoperator kopieren/verschieben definieren, müssen Sie * all * davon definieren. Beachten Sie, dass gelöschte Definitionen weiterhin zählen (z. B. für Nur-Verschiebe-Klassen). – o11c

Antwort

1

Weil Sie etwas im Stapel löschen. Wenn Sie den Zeiger einer Referenz auf eine lokale Variable zuweisen, weisen Sie den Zeiger einer im Stapel zugewiesenen Entität zu. Es kann nicht mit "löschen" gelöscht werden, was für Heap-Variablen ist. Darüber hinaus leugnen Sie, was Sie mit dem neuen zugewiesen haben.

TestState test; 

    State *state = new State(); 
    state = &test; //Now it points to the test which is in the stack 

    state->Init(); 

    delete state; //Delete something in the stack. Not good. 

So etwas sollte besser funktionieren.

TestState test; 

    State *state = &test; 

    state->Init(); 
+0

Ich habe das versucht, und es gab mir immer noch den gleichen Fehler, irgendwelche Ideen? – Dramentiaras

+0

Arbeitete für mich in VS2015, (in diesem Fall ist das Löschen nicht erforderlich, da Sie nichts auf dem Heap zuweisen). –

+0

Aah, tut mir leid. Vergessen, das Löschen zu entfernen. Es funktioniert jetzt! – Dramentiaras

1

Auch wenn die Lösung Ihrer spezifischen Problem war einfach (das heißt Sie versuchen, einen Stapel zugewiesene Variable zu löschen, als ob es Heap zugewiesen war), wollte ich meine Lösung für mein mysteriös RtlValidateHeap Behauptung posten.

Es stellt sich heraus, dass der Code, an dem ich arbeitete, gemischte Einstellungen zwischen Projekten für "Laufzeitbibliothek" hatte (in den Projekteigenschaften, unter C/C++ -> Codegenerierung). Die Anwendung hat "Multithreaded Debug", die DLLs hatten "Multithreaded Debug DLL". Sie müssen alle auf dieselbe Sache eingestellt sein.

Wenn Sie DLL- und Nicht-DLL-Laufzeitbibliotheken mischen, erhalten Sie zwei separate Heaps, und es wird unmöglich, ein unter einer Laufzeitbibliothek zugeordnetes Objekt aus Code mit einer anderen Laufzeitbibliothek zu löschen. Du erhältst mysteriöse RtlValidateHeap Assertions.

Hoffe das hilft jemand anderem.

Verwandte Themen