2009-05-12 3 views
4

Ich verwende Visual Studio und führe eine gültige dynamische Besetzung durch. RTTI ist aktiviert.Wann und warum wird eine std :: __ non_rtti_object-Ausnahme generiert?

Edit: der Code aktualisiert realistischere

struct base 
{ 
    virtual base* Clone() 
    { 
     base* ptr = new base; 
     CopyValuesTo(ptr); 
     return ptr; 
    } 
    virtual void CopyValuesTo(base* ptr) 
    { 
     ... 
    } 
    virtual ~base() 
    { 
    } 
} 

struct derived : public base 
{ 
    virtual base* Clone() 
    { 
     derived* ptr = new derived; 
     CopyValuesTo(ptr); 
     return ptr; 
    } 
    virtual void CopyValuesTo(base* ptr) 
    { 
     ... 
    } 
    virtual ~derived() 
    { 
    } 
} 

void Class1::UseNewSpec(base* in_ptr) //part of a totally unrelated class 
{ 
    derived* ptr = dynamic_cast<derived *>(in_ptr); 
    if(!ptr) 
     return; 
    delete m_ptr; 
    m_ptr = ptr->Clone(); //m_ptr is a member of Class1 of type base* 
} 

//usage : 
Class1 obj; 
derived new_spec; 
obj.UseNewSpec(&new_spec); 

Mein Debugger zu sein, sagt, dass in_ptr vom richtigen Typ ist, wenn die Ausnahme ausgelöst wird. Google scheint besonders wenig hilfreich zu sein. Irgendwelche Ideen? Prost.

+0

Geben Sie einen echten Code ein. – dirkgently

+0

Hier ist ein Verwendungsszenario: UseNewSpec ist mit einem GUI-Regler verknüpft. Wenn der Knopf geändert wird, wird UseNewSpec aufgerufen. Es funktioniert, wenn der Knopf langsam bewegt wird, aber dies macht den Unterschied, wenn er sich sehr schnell bewegt. – Carl

+0

Danke Jungs.Ich habe es herausgefunden. Es war ein Threading-Problem - etwas schäbiger Code an anderer Stelle führte dazu, dass der Zeiger unmittelbar vor der Dynamic-Umwandlung ungültig wurde. – Carl

Antwort

5

Ich habe einen Test auf Ihrem Pseudocode ausgeführt und es funktioniert. Wenn also RTTI in Ihrer Build-Konfiguration wirklich aktiviert ist, muss es sich um ein weiteres Problem handeln, das nicht in den von Ihnen geposteten Daten enthalten ist.

+3

Falls jemand in Zukunft auf diesen Beitrag zugreift, hatte ich ein ähnliches Problem und es stellte sich heraus, dass ich in meinem Code etwas Dummes tat: Ich löschte ein Objekt auf dem (gültigen, nicht NULL) Zeiger von 'dynamic_cast' und Dann fuhr ich fort, 'dynamic_cast' auf dem gleichen ursprünglichen Zeiger später aufzurufen. Das ist wahrscheinlich nicht das Problem für diese Frage, aber ich bemerke das nur für den Fall, dass jemand anderes in diese Frage als etwas Einfaches hineinstolpert. –

+2

Es war ein sehr ähnliches Problem für mich. Der Unterschied bestand darin, dass der schäbige Code an anderer Stelle, der den Zeiger löschte, den ich verwendete, den Zeiger nicht einmal auf NULL setzte. Daher erschien es gültig, aber die dynamische Besetzung war immer noch nicht erfolgreich. – Carl

+2

hatte das selbe Problem wie ihr Leute und ruft 'dynamic_cast <>' auf dem baumelnden Zeiger auf. Vielen Dank – azf

5

RTTI-Ausnahmen, Fehler oder Fehler in der Umgebung von dynamic_cast können bedeuten, dass Sie eine ungültige Besetzung durchgeführt haben. dynamic_cast<derived*>(ptrToBase) ist nur dann gültig, wenn die Klassen derived und base die folgende Bedingung erfüllen: Diese Klasse oder eine ihrer Basisklassen hat eine virtuelle Memberfunktion.

Diese virtuelle Elementfunktion kann alles sein, einschließlich des Destruktors. Wenn Sie keine anderen Elementfunktionen haben, können Sie versuchen:

struct base 
{ 
    virtual ~base(){} 
    ... 
} 

struct derived : public base 
{ 
    ... 
} 

Jetzt base eine virtuelle Member-Funktion hat, und so ist abgeleitet. Probieren Sie es aus und sehen Sie, ob es Ihr Problem löst.

EDIT-ADD:

@carleeto - In "hatte es bereits einen virtuellen Destruktor", es doe == Basis?

Wenn abgeleitet hat virtuellen Destruktor aber Basis ist nicht virtuelles dtor, dann können Sie immer noch diesen Fehler erhalten.

Außerdem sollten Sie überprüfen, dass das Objekt nicht zerstört wurde - sobald der Destruktor ausgeführt wird, ist dynamic_cast nicht mehr sicher zu rufen. Versuchen Sie, den Ctors und Dtors eine Ablaufverfolgung hinzuzufügen.

+0

Es hatte bereits einen virtuellen Destruktor. Meine Schuld - ich hätte das anzeigen sollen. – Carl

+0

@carleeto - bearbeiten hinzufügen, siehe neue Antwort – Aaron

0

Enthält base irgendwelche virtual Methoden? Es muss für dynamic_cast arbeiten.

+0

Ja, tut es. Entschuldigung, ich hätte das zum Code hinzufügen sollen. – Carl

+0

Ich habe gerade den Code aktualisiert. – Carl

8

http://msdn.microsoft.com/en-us/library/fyf39xec(VS.80).aspx hat Informationen zu __non_rtti_object_exception.

Von MSDN:

Wenn der Zeiger auf ein gültiges Objekt wird ein __non_rtti_objectexception geworfen, was auf einen Versuch zeigt nicht die RTTI zu analysieren, damit einen Fehler ausgelöst (wie Zugang Verletzung), weil das Objekt irgendwie ungültig ist (schlechter Zeiger oder Code wurde nicht mit/GR kompiliert).

+0

/GR bedeutet aktivieren RTTI. Es ist bereits standardmäßig aktiviert./GR- schaltet es aus. Auch das explizite Hinzufügen von/GR zur Kommandozeile hilft nicht. – Carl

1

Stellen Sie sicher, dass RTTI in allen Quelldateien aktiviert ist.

Andernfalls ist der Zeiger ungültig.

Verwandte Themen