[Downcast] dynamic_cast, aber wie?



  • Hi,

    arbeite mti VC und nutze der Xerces-Lib. Gerade hab ich alle C-Casts in C++-Cast umgeschrieben und da fliegen plötzlich Ausnahmen rum 😮 :

    Eine Ausnahme (erste Chance) bei 0x10227637 (msvcr71d.dll) in TestDaRest.exe: 0xC0000005: Zugriffsverletzung-Leseposition 0x0000007d.
    Eine Ausnahme (erste Chance) bei 0x77e7a4e1 in TestDaRest.exe: Microsoft C++ exception: __non_rtti_object @ 0x0012f850.

    Verursacht durch eine Cast, der mit C-Style kein Problem war:

    XERCES DOMNode* pListXElem = 
    				(dynamic_cast<XERCES DOMNodeList*>(pElem->getElementsByTagName(X(
    				Distribution::getElementName().c_str()))))->item(0);
    			XERCES DOMElement* pListElem = dynamic_cast<XERCES DOMElement*>
    				(pListXElem);
    

    Mit dem zweiten Cast kommt's geflogen, was aber laut Doku nicht sein sollte (zu getElementsByTagName()):

    Returns:
    A list of matching DOMElement nodes.

    Und nun?
    Weiss jemand rat (ausser wieder auf C-Casts umzustellen)?

    Danke,
    don_basto



  • Hast du die RunTimeTypeInformation (RTTI) aktiviert?
    Diese wird für dynamic_cast <> benötigt.



  • Ja, ist die Compiler-Option /GR. Allerdings hat die Einstellung auf des Ergebnis keinen Einfluss, es fallen nur ein paar Warnungen weg.
    Ich vermute, dass es der Xerces-Lib liegt, wie soll der Compiler da die Klassenhierarchie ohne den Quellkode rausfinden, um zu bestimmen, dass der Downcast ok ist?



  • frage: wo hast du die Doku zu xerces her?
    Bei meinem Download war zwar was dabei. aber das war nicht wirklich aussagekräftig ... .



  • Ähm ohne die Xerces-Bibliothek zu kennen - warum muss man auf das Ergebnis einer Funktion nen dynamic_cast machen? 😮

    Anhand deiner Exceptions muss das ja heißen, dass die Bibliothek ohne RTTI übersetzt wurde. Also wohl auch nicht dafür vorgesehen ist, von ihr abzuleiten und sie polymorph zu benutzen.



  • Hab von http://xml.apache.org/xerces-c/.
    Hab in der MSDN folgendes gefunden:

    If the expression is dereferencing a pointer, and that pointer's value is zero, typeid throws a bad_typeid exception. If the pointer does not point to a valid object, a __non_rtti_object exception is thrown, indicating an attempt to analyze the RTTI that triggered a fault (like access violation), because the object is somehow invalid (bad pointer or the code wasn't compiled with /GR).

    Nun schliesse ich daraus, dass ich die Quelldateien mit dem VC und /GR compilieren muss, um eine ordentliche Laufzeitprüfung hinzubekommen. Hmm.

    @7H3 N4C3R:
    Weil C++-Kode schreiben will und C++ für Downcasts eben dynamic_cast vorsieht. Vielleicht haben die Xerces-Entwickler nicht daran gedacht. 😉
    // EDIT: Ausserdem kann man mit einem DOMElement mehr anfangen, als mit einem DOMNode. Abgeleitet habe ich selbst nicht, ich cast zwischen 2 ganz offiziellen Xerces-Klassen.



  • Hab's mir mal angeschaut.

    Also...
    1.: was hast das "Xerxes" da oben in den casts zu suchen?
    2.: Die Bibliothek gibt's im Source. Wenn Sie tatsächlich
    ohne RTTI übersetzt ist, übersetz sie neu mit RTTI.
    3.: Hat das Programm überhaupt schonmal funktioniert?



  • 7H3 N4C3R schrieb:

    Hab's mir mal angeschaut.

    Also...
    1.: was hast das "Xerxes" da oben in den casts zu suchen?
    2.: Die Bibliothek gibt's im Source. Wenn Sie tatsächlich
    ohne RTTI übersetzt ist, übersetz sie neu mit RTTI.
    3.: Hat das Programm überhaupt schonmal funktioniert?

    1.: Das ist ein Makro für den Xerces namespace, da ich Xerces nur in wenigen Methoden benutze.
    2.: Hab ich vor, hatte gehofft, das zu vermeiden.
    3.: Lies den ersten Beitrag! Mit C-Casts läufts ohne Probs.



  • Makros, pfui 🙂 Ich mag die Dinger nicht. Meine dritte Frage war deshalb, weil aus deinem ersten Code nicht wirklich hervorgeht, dass das Programm auch funktioniert (d.h. was sinnvolles tut). Im Gegenteil, da Ausnahmen kommen, legt das eher ein fehlerhaftes Programm nahe (auch wenn die Fehler durch die Bibliothek kommen).



  • denk ich auch. warscheinlich ist pListXElm gleich 0 oder so. mit dem dynamic_cast<> an sich hat die fehlermeldung nichts zu tun.



  • @7H3 N4C3R:
    Das Problem ist, dass mir nach der Änderung von C-Casts in C++-Casts dieser Downcast mit dynamic_cast eine Ausnahme wirft. Eigentlich sollte der C++-Cast eine höhere Sicherheit gewährleisten, da er nur genau einen bestimmten, den Dowmcast, durchführt und falls das nicht geht, einfach NULL zurückgibt. Aber stattdessen bekomme ich eine Ausnahme. 😕

    @Konfusius:
    Da steht ein ordentliches Objekt dahinter, mit dem man alles machen kann, nur keinen dynamic_cast. 😉

    Der oben beschriebene Fehler weist lt. MSDN darauf hin, das Objekt nich valid ist (ist es aber, mit C-Casts funzt es!) oder der Code nicht mit RTTI kompiliert wurde(aha!). Also Quelltext von XERCES besorgen und neu kompilieren.
    Aber nur um ordentlichen C++-Kode zu schreiben dann diesen ganzen Aufwand betreiben, das will ich nicht glauben. Wieso sollte man dann auf C++-Cast umsteigen?
    Was, wenn die Libs nicht im Quellkode vorliegen, dann eben auf dynamic_cast verzichten?



  • Genaugenommen ist der C-Cast ein Schuss ins Blaue. Wenn Du weißt, dass ein bestimmter konkreter Typ hinter der Basisklasse steht, mag das funktionieren - sicher ist es aber nicht.
    Ich finde es nicht wirklich sinnvoll, dass eine C++ Bibliothek die polymorph verwendet werden soll, ohne RTTI ausgeliefert wird. Okay, genauso schwachsinnig ist es, dass in VC++6 RTTI per default aus ist. Sollte man die Xerces-Leute vielleicht mal drauf hinweisen - dass sie zumindest eine Version mit und eine ohne RTTI hinstellen. Selberbauen ist sonst immer die einzige Alternative.



  • Microsoft's C++ Code verwendet weder Exceptions noch RTTI. Viele Entwickler folgen dem Beispiel.

    Wenn man Exceptions oder RTTI in einem eigenen Projekt verwendet, muß man sicherstellen, daß die Schnittstellen zu externen Bibliotheken diese Eigenheiten entsprechend kapseln.

    Z.B. einen OLE-Methoden-Aufruf kapseln in dem man den Return-Wert abfängt und eine Exception erzeugt. Oder einen Datentyp z.B. per static_cast<> oder C-Cast casten und erst in darüberliegendem Code dynamic_cast<> verwenden.



  • Danke für die Antworten. Hab jetzt erstmal wieder auf C-Cast umgestellt, da ich den Zeitaufwand für selber Kompilieren zu gross einschätze. Hab bisher nur einmal mit make-files gearbeitet und es mit VC nicht hinbekommen.

    Cya,
    don_basto


Anmelden zum Antworten