GetWindowLong, cast & méthodes virtuelles

Résolu
MyXiLo Messages postés 57 Date d'inscription vendredi 21 mai 2004 Statut Membre Dernière intervention 28 juillet 2006 - 1 juin 2006 à 20:51
ymca2003 Messages postés 2070 Date d'inscription mardi 22 avril 2003 Statut Membre Dernière intervention 3 juillet 2006 - 2 juin 2006 à 09:41
Bonsoir,

Mon soucis est que, lorsque je cast le resultat d'un GetWindowLong en un pointeur, l'appel d'une fonction virtuelle de l'objet pointe provoque une erreur lors de l'execution ("Unhandled exception at 0x0040149c in Ivy.exe: 0xC0000005: Access violation reading location 0x00000000.", avec VS 2005).

class MaClasse
{
    virtual void MaFonction();
}

static LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    MaClasse *MonObjet=(MaClasse *)GetWindowLong(hwnd, GWL_USERDATA);
    MonObjet->MaFonction(); // Genere une erreur si MaFonction est déclarée virtual
}

(Je precise que ma WindowProcedure est bien definie pour une WNDCLASSEX appartenant à MaClasse(dans cet exemple)).

Ce serait une erreur de debutant que ca n'aurait rien d'etonnant puisque j'en suis un :}.

Merci d'avance.
Thomas.

10 réponses

vecchio56 Messages postés 6535 Date d'inscription lundi 16 décembre 2002 Statut Membre Dernière intervention 22 août 2010 14
1 juin 2006 à 21:08
C'est plutot bizarre ca... Pour tester, tu peux essayer ca:

MaClasse* o1 = new ...;
LPARAM l = (LPARAM)o1;
MaClasse* o2 = (MaClasse)l;
o2->MaFonction();

Au pire, compare les adresse des objets de départ (au moment du SetWindowLong) et à l'arrivée (GetWindowLong). Je suppose qu'ils seront différents
(c'est comme ca que j'avais détecté le problème quand je l'avais eu)
3
vecchio56 Messages postés 6535 Date d'inscription lundi 16 décembre 2002 Statut Membre Dernière intervention 22 août 2010 14
1 juin 2006 à 20:56
J'ai déja eu ce problème. Au moment du SetWindowLong, il faut que tu castes en (MaClasse*) (j'imagine que le vrai type de l'objet n'est pas MaClasse, mais un sous-type de MaClasse)
0
MyXiLo Messages postés 57 Date d'inscription vendredi 21 mai 2004 Statut Membre Dernière intervention 28 juillet 2006
1 juin 2006 à 21:04
Je cast deja en (MaClasse *) au moment du SetWindowLong en realite.
Effectivement c'est un sous-type, mais, meme si MaClasse n'est pas derivee, ca pose tout de meme un probleme.

Merci pour cette reponse tres rapide.
0
Zootella Messages postés 252 Date d'inscription vendredi 10 juin 2005 Statut Membre Dernière intervention 5 septembre 2006
1 juin 2006 à 21:34
Si le retour de GetWindowLong est NULL, c'est logique que ça plante.

Test l'objet avant de l'utiliser.
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
vecchio56 Messages postés 6535 Date d'inscription lundi 16 décembre 2002 Statut Membre Dernière intervention 22 août 2010 14
1 juin 2006 à 21:35
Apparemment ca plante seulement quand la méthode est virtuelle
0
MyXiLo Messages postés 57 Date d'inscription vendredi 21 mai 2004 Statut Membre Dernière intervention 28 juillet 2006
1 juin 2006 à 22:41
En fin de compte je viens de me rendre compte que c'est mon SetWindowLong qui ne fonctionnait pas. Je castais en (long) le pointeur que jobtenais precedement avec GetWindowLong en (MaClasse *). Mais, comme SetWindowLong n'etais pas encore appele au moment du GetWindowLong, cela renvoyait 0, que je passais ensuite a SetWindowLong apres l'avoir caste en (long). Ce qui etait donc tres stupide.

Du coup j'ai mis mon SetWindowLong juste après le CreateWindowEx, en lui passant (long)this en troisieme parametres, et ca marche parfaitement.

C'etait tout a fait idiot comme probleme.

Merci beaucoup pour tes reponses.
Thomas.
0
MyXiLo Messages postés 57 Date d'inscription vendredi 21 mai 2004 Statut Membre Dernière intervention 28 juillet 2006
1 juin 2006 à 22:43
Oui en revanche ce qui est etrange cest que ca ne marchait pas uniquement pour les fonctions virtuelles...
0
Zootella Messages postés 252 Date d'inscription vendredi 10 juin 2005 Statut Membre Dernière intervention 5 septembre 2006
1 juin 2006 à 23:04
Oui en revanche ce qui est etrange cest que ca ne marchait pas uniquement pour les fonctions virtuelles...

C'est logique, tu as appelé
MaFonction avec this = NULL.

On peut appeler les fonctions d'une classe avec un pointeur NULL, seulement la classe ne doit pas avoir de variables membres.

Or pour gérer les fonctions virtuelles, le compliteur rajoute une variable membre caché, un pointeur sur la table virtuelle.

Quand tu appele MaFonction, ce pointeur est déréférencé, donc plantage.
0
MyXiLo Messages postés 57 Date d'inscription vendredi 21 mai 2004 Statut Membre Dernière intervention 28 juillet 2006
2 juin 2006 à 00:00
Merci beaucoup pour cette precision.
Thomas.
0
ymca2003 Messages postés 2070 Date d'inscription mardi 22 avril 2003 Statut Membre Dernière intervention 3 juillet 2006 7
2 juin 2006 à 09:41
Attention également à la façon de gérer cette sauvegarde de ptr dans le GWL_USERDATA.

Si le ptr à savegarder dans est passé lors de CreateWindow, il sera dans la structure CREATESTRUCT pointée pr lParam lors du traitement des message WM_NCCREATE et WM_CREATE.

Le piège c'est qu'avant ces messages, d'autres sont susceptible d'être traité (je sais plus lesquels)donc le ptr n'est pas encore mis dans GWL_USERDATA. Il faut dont testé le ptr avant...
0
Rejoignez-nous