Der ganze Fehler lässt sich mit folgendem Testfall reproduzieren:
//TestLib.hpp
class Base {
public:
virtual ~Base() {}
};
template <typename T>
class Derived : public Base {
public:
Derived();
};
/*TestLib.cpp
* compile with: g++ -dynamiclib TestLib.cpp -o libTestLib.dylib
*/
#include "TestLib.hpp"
#include <typeinfo>
#include <iostream>
template <typename T>
Derived<T>::Derived() {
std::cout << typeid(*this).name() << std::endl;
}
template class Derived<int>;
Wie man in der letzten Zeile sieht wird das Template
Derived
explizit mit int
in TestLib.cpp instanziiert. Diesen Typen werden wir jetzt in einer kleinen Anwendung etwas durch die Typhierarchie scheuchen und ein sehr seltsames Verhalten beobachten.
/* main.cpp
* compile with: g++ -L. -lTestLib main.cpp -o main
*/
#include "TestLib.hpp"
#include <iostream>
int main() {
Derived<int>* i = new Derived<int>();
std::cout << typeid(*i).name() << std::endl;
Base *o = i;
std::cout << typeid(*o).name() << std::endl;
std::cout << o << std::endl;
std::cout << dynamic_cast< Derived<int>* >(o) << std::endl;
std::cout << typeid(*o).name() << std::endl;
delete i;
}
Wir erhalten folgende Ausgabe:
7DerivedIiE
7DerivedIiE
0x100100080
0
7DerivedIiE
Die Typid verändert sich nicht und trotzdem liefert ein gültiger Downcast den Nullpointer zurück. Ich habe den Code ebenfalls unter FreeBSD und DragonflyBSD getestet, in beiden Fällen war der Downcast erfolgreich. Meines Wissens tritt dieses Verhalten erst seit Snow Leopard auf, aber da ich derzeit nirgends eine aktuelle Version von Leopard laufen habe kann ich nicht testen ob es sich hier um einen neuen Bug handelt.
Der einzige Workaround der mir derzeit einfällt ist die Instanziierung des Templates in die Compilezeit der Anwendung zu verlegen.
UPDATE: Mal ein delete nachgebessert, nicht das sich hier noch jemand beschwert das mein Testcase leakt :P
2 Kommentare:
Leider kann ich das Problem bestätigen. Unter 10.5 bestand dies noch nicht. Ich musste meinen Code umstellen und alles in eine Bibliothek packen - leider.
Das Problem ist unabhängig vom Compiler ob Apple's 4.2 oder der neuste gcc 4.4.1.
Bin selber an einer Lösung sehr interessiert.
Beste Grüsse,
S. Stingelin.
Das Problem scheint im GCC Code zu liegen. Ich hab mal nachgeforscht und mir wurde ein Link zum Bugtracker von GCC gegeben. Habe ihn aber leider verschlampt. Leider habe ich auch keine wirkliche Lösung für das Problem außer halt Code zu verschieben oder das Design verändern und auf solche Instanziierungen zu verzichten. Mich würde interessieren was andere Compiler in dem Fall machen.
Gruß
raichoo
Kommentar veröffentlichen