[Probleme] Dynamic_cast<T>(x) - Unix Segfault

Dynamic_cast<T>(x) - Unix Segfault [Probleme] - C++ - Programmation

Marsh Posté le 11-12-2008 à 09:48:41    

Bonjour a tous,
 
Je suis actuellement en train de coder une "abstraction", mais j'ai un petit (Enfin gros) problème.
Notre programme doit fonctionner sur Windows et sur Unix.
 
Nos tests sur Windows se sont déroules avec succès.
Mais c'est la que ca se corse... sur notre version de Unix (FreeBSD 7.1 et g++ 3.4.2, pour info nous ne pouvons pas changer de version de g++) il y a un SegFault au moment d'un dynamic_cast<T>(x).
 

Citation :


back = dynamic_cast<X>(actual->methode(*autre));
 
// Renvois un objet bien Type en X (Sachant X est une interface et que le type de actual hérite de cette même interface)
// mais qui pointe sur NULL
// Et au moins sur Windows ca marche...

 
if (back != NULL)
{
 ...
}
else
{
 ...
}


 
Apres de multiples recherches, j'ai trouvé des infos sur un fameux RTTI (Run-Time Type Information, CFLAGS += -fno-rtti) à activer sur g++ mais sans succès.
 
Si vous avez des infos je suis preneur !
Merci d'avance :hello:


---------------
Benchmarks du peuple - Crysis War - Vide grenier ! - nVIDIA Tegra
Reply

Marsh Posté le 11-12-2008 à 09:48:41   

Reply

Marsh Posté le 11-12-2008 à 23:12:30    

Bon voila problème résolue.
 
C'est juste que Unix c'est moisi ! (ce n’est pas un troll, après deux ans dessus, j'apprécie toujours pas ...), même si Windows et tous ces #define …..
 
Passons aux choses sérieuses, je développe au cas où ca pourrait servir.
En faite, j'avais oublié de préciser que l'abstraction Windows / Unix se faisait au niveau du chargement / déchargement de librairies dynamiques (.so et .dll)
Le problème est bien au niveau de Unix, quand il créer les .so, il perd des information (comme l'héritage, comme quoi Unix...), qui ne lui permet pas de savoir que le type de note objet actual est un objet qui hérite de la class X.
Donc il faut impérativement utiliser un reinterpret_cast<T>().
 
Bon voila, si ca peut aider quelqu’un à l’avenir !
:hello :


---------------
Benchmarks du peuple - Crysis War - Vide grenier ! - nVIDIA Tegra
Reply

Marsh Posté le 12-12-2008 à 07:21:18    

kaiser52 a écrit :

Bon voila problème résolue.
 
C'est juste que Unix c'est moisi ! (ce n’est pas un troll, après deux ans dessus, j'apprécie toujours pas ...), même si Windows et tous ces #define …..
 
Passons aux choses sérieuses, je développe au cas où ca pourrait servir.
En faite, j'avais oublié de préciser que l'abstraction Windows / Unix se faisait au niveau du chargement / déchargement de librairies dynamiques (.so et .dll)
Le problème est bien au niveau de Unix, quand il créer les .so, il perd des information (comme l'héritage, comme quoi Unix...), qui ne lui permet pas de savoir que le type de note objet actual est un objet qui hérite de la class X.
Donc il faut impérativement utiliser un reinterpret_cast<T>().
 
Bon voila, si ca peut aider quelqu’un à l’avenir !
:hello :


Mais tu racontes n'importe quoi ...
Y a pas à de flag à activer, sauf pour désactiver les RTTI ... si ça segfault, c'est probablement que actual ou autre vaut 0. Sort ton debugger et tu trouveras. Y a rien de mystique.
 
Et c'est certainement pas en CFLAGS += -fno-rtti en disant au compilateur __C__ de désactiver les rtti que ça va mieux marcher.
 
Reprend ça tranquillement. Les RTTI sont bien exportées dans les DSO.

Reply

Marsh Posté le 12-12-2008 à 09:36:49    

Peut-être que ce serait une donnée, qui serait supposément initialisée à null par défaut, alors que ce ne serait pas le cas, sauf dans certaines circonstances.

Reply

Marsh Posté le 12-12-2008 à 09:54:06    

kaiser52 a écrit :


Bon voila, si ca peut aider quelqu’un à l’avenir !


Sauf que tu dis du caca :€
T'as un bug ailleurs et c'est tout.

 

EDIT [:grillaid]


Message édité par Joel F le 12-12-2008 à 09:54:15
Reply

Marsh Posté le 12-12-2008 à 10:05:31    

Tu as du quotter le mauvais post.
Dans celui la je ne parle plus de RTTI (Surtout que je me suis rendu compte qu'il n'y avait pas de rapport).
 
Mais il y à bien un problème avec les .so.
 
Être obliger d'utiliser un reinterpret_cast<T>() c'est quand même crade pour un si petit programme (pourquoi pas utiliser un cast "C" histoire de pas savoir quel cast va être appliqué).
Surtout que le dynamic_cast<T>() fonctionne très bien sur Windows, et bien sure la parti ou "ça plante" sur Unix n'est pas une parti abstraite, donc le même code sur Windows / Unix
 
En gros dans le programme au chargement dynamiques des librairies, on appelle une méthode GetObject() qui nous renvois un new Class_de_la_ld qui est stocké dans une map<std::string nom_de_la_ld, IInterfaceObject* pointer_sur_la_class>, ensuite nous utilisons la méthode clone() de Class_de_la_ld pour dupliquer ou recréer un objet du même type (design prototype) en fonction de la demande.
Parmi les directives, toutes les méthodes de la Class_de_la_ld doivent renvoyer un IInterface*.
 
Sachant que :
Class_de_la_ld hérite de IInterfaceObject qui elle même hérite de IInterface.
 
D'ou le probléme et l'obligation de caster.


---------------
Benchmarks du peuple - Crysis War - Vide grenier ! - nVIDIA Tegra
Reply

Marsh Posté le 12-12-2008 à 10:15:27    

je pencherais plus pour un bug de 3.4 qu'autre chose.  
J'ai un système équivalent dans un gros projet et ca marche sans pb sous nix.
 
Je compile avec 4.3

Reply

Marsh Posté le 12-12-2008 à 10:21:17    

Joel F >>
 
Je t'expose le schema :
 
                                                      Windows                   Unix
Chargement des librairies :                      OK                        OK                    Code Différent
( Ainsi que dans la map)
 
Acces aux methodes de
la Class_de_la_dl via IInterface :              OK                        OK                    Code Identique
(Methodes hérité)
 
/*
** Contenu de toutes les variables du programme
** identique entre Unix et Windows à ce niveau du programme
*/

 
Cast de IInterface en IInterfaceObject      OK                      ECHEC                 Code Identique
Dynamic_cast<T>()                                                      Pointer NULL
(Methodes hérité)
 
Cast de IInterface en IInterfaceObject      OK                       OK                    Code Identique
reinterpret__cast<T>()
 
/*
** Contenu de toutes les variables du programme
** identique entre Unix et Windows à ce niveau du programme
*/

 
Acces aux methodes de  
la Class_de_la_dl via IInterfaceObject       OK                         OK                    Code Identique
 
Déchargement des librairies :                   OK                         OK                    Code Différent
 
Si le dynamic_cast<T>() marche sur Windows c'est qu'il doit marcher sur Unix.
Le reinterpret_cast<T>() permet convertir tous en tous, donc c'est normal que ça marche, et si la suite se déroule correctement c'est bien que l'objet qui est typé IInterface peut aussi être typé IInterfaceObject car il contient bien ces méthodes.
 
Edit :
 
Le probleme c'est que l'on à pas le droit de changer de version de GCC.


Message édité par kaiser52 le 12-12-2008 à 10:22:11

---------------
Benchmarks du peuple - Crysis War - Vide grenier ! - nVIDIA Tegra
Reply

Marsh Posté le 12-12-2008 à 11:29:47    

ca sent le foirage de gcc ça :/
Je vais voir à tester mon projet avec  3.4

Reply

Marsh Posté le 12-12-2008 à 11:36:29    

J'ai trouvé ça :
 
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=9433
 

Citation :

   The Segfault happens in the runtime support libs (with 3.4):
     
    (gdb) bt
    #0  0x4006c7a2 in __cxxabiv1::__vmi_class_type_info::__do_find_public_src(int, void const*, __cxxabiv1::__class_type_info const*, void const*) const (
        this=0x804a4a0, src2dst=-1, obj_ptr=0x0, src_type=0x804a488,  
        src_ptr=0xbffff184)
        at ../../../../gcc-3.4-CVS/libstdc++-v3/libsupc++/tinfo.cc:122
    #1  0x4006cd0d in __cxxabiv1::__vmi_class_type_info::__do_dyncast(int, __cxxabiv1::__class_type_info::__sub_kind, __cxxabiv1::__class_type_info const*, void const*, __cxxabiv1::__class_type_info const*, void const*, __cxxabiv1::__class_type_info::__dyncast_result& ) const (this=0x804ab60, src2dst=-1,  
        access_path=__contained_public, dst_type=0x804a4a0, obj_ptr=0xbffff174,  
        src_type=0x804a488, src_ptr=0xbffff184, result=@0xbffff120)
        at ../../../../gcc-3.4-CVS/libstdc++-v3/libsupc++/tinfo.cc:264
    #2  0x4006d0c3 in __dynamic_cast (src_ptr=0xbffff184, src_type=0x804a488,  
        dst_type=0x804a4a0, src2dst=-1)
        at ../../../../gcc-3.4-CVS/libstdc++-v3/libsupc++/tinfo.cc:712
    #3  0x08048703 in main () at x.cc:19
     
    W.


 
 :jap:


---------------
Benchmarks du peuple - Crysis War - Vide grenier ! - nVIDIA Tegra
Reply

Marsh Posté le 12-12-2008 à 11:36:29   

Reply

Marsh Posté le 12-12-2008 à 12:40:06    

t'es bien en -fPIC ?
 
g++ -c -fPIC interface.cpp
g++ -shared -o libinterface.so interface.o
g++ -L. -linterface main.cpp
LD_LIBRARY_PATH=. ./a.out
 
et hop tu roules.

Reply

Marsh Posté le 12-12-2008 à 12:41:34    

kaiser52 a écrit :

J'ai trouvé ça :
 
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=9433
 

Citation :

   The Segfault happens in the runtime support libs (with 3.4):
     
    (gdb) bt
    #0  0x4006c7a2 in __cxxabiv1::__vmi_class_type_info::__do_find_public_src(int, void const*, __cxxabiv1::__class_type_info const*, void const*) const (
        this=0x804a4a0, src2dst=-1, obj_ptr=0x0, src_type=0x804a488,  
        src_ptr=0xbffff184)
        at ../../../../gcc-3.4-CVS/libstdc++-v3/libsupc++/tinfo.cc:122
    #1  0x4006cd0d in __cxxabiv1::__vmi_class_type_info::__do_dyncast(int, __cxxabiv1::__class_type_info::__sub_kind, __cxxabiv1::__class_type_info const*, void const*, __cxxabiv1::__class_type_info const*, void const*, __cxxabiv1::__class_type_info::__dyncast_result& ) const (this=0x804ab60, src2dst=-1,  
        access_path=__contained_public, dst_type=0x804a4a0, obj_ptr=0xbffff174,  
        src_type=0x804a488, src_ptr=0xbffff184, result=@0xbffff120)
        at ../../../../gcc-3.4-CVS/libstdc++-v3/libsupc++/tinfo.cc:264
    #2  0x4006d0c3 in __dynamic_cast (src_ptr=0xbffff184, src_type=0x804a488,  
        dst_type=0x804a4a0, src2dst=-1)
        at ../../../../gcc-3.4-CVS/libstdc++-v3/libsupc++/tinfo.cc:712
    #3  0x08048703 in main () at x.cc:19
     
    W.


 
 :jap:

j'ai un version gcc 3.4.6 20060404 (Red Hat 3.4.6-8) sur RHEL4.5 aucun pb. Vérifie de bien faire comme je t'ai dit.

Reply

Marsh Posté le 12-12-2008 à 12:48:14    

hum, ça sent le vainqueur -c -shared . C'est incompatible, vu que -c empêche le link, du coup tous tes symboles vers libstdc++ et donc le runtime nécessaire aux RTTI  ne sont pas résolus ... boum

Reply

Marsh Posté le 12-12-2008 à 13:06:20    

Bon bah merci de la tentative quand même ^^
Pour le moment je reste comme ça (avec le reinterpret_cast<T>()) vue que ça marche.


---------------
Benchmarks du peuple - Crysis War - Vide grenier ! - nVIDIA Tegra
Reply

Marsh Posté le 12-12-2008 à 14:23:20    

kaiser52 a écrit :

Bon bah merci de la tentative quand même ^^
Pour le moment je reste comme ça (avec le reinterpret_cast<T>()) vue que ça marche.


ouais je brasse du vent quoi. je me casse.

Reply

Marsh Posté le 12-12-2008 à 14:37:54    

Bah tu t'es contredis tous seul :??:
Et tu te clashe tous seul !  :heink:  
 
Je ne pige pas là !


---------------
Benchmarks du peuple - Crysis War - Vide grenier ! - nVIDIA Tegra
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed