GetWindowLong, cast & méthodes virtuelles [Résolu]

Signaler
Messages postés
57
Date d'inscription
vendredi 21 mai 2004
Statut
Membre
Dernière intervention
28 juillet 2006
-
Messages postés
2070
Date d'inscription
mardi 22 avril 2003
Statut
Membre
Dernière intervention
3 juillet 2006
-
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.
A voir également:

10 réponses

Messages postés
6535
Date d'inscription
lundi 16 décembre 2002
Statut
Modérateur
Dernière intervention
22 août 2010
7
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)
Messages postés
6535
Date d'inscription
lundi 16 décembre 2002
Statut
Modérateur
Dernière intervention
22 août 2010
7
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)
Messages postés
57
Date d'inscription
vendredi 21 mai 2004
Statut
Membre
Dernière intervention
28 juillet 2006

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.
Messages postés
252
Date d'inscription
vendredi 10 juin 2005
Statut
Membre
Dernière intervention
5 septembre 2006
1
Si le retour de GetWindowLong est NULL, c'est logique que ça plante.

Test l'objet avant de l'utiliser.
Messages postés
6535
Date d'inscription
lundi 16 décembre 2002
Statut
Modérateur
Dernière intervention
22 août 2010
7
Apparemment ca plante seulement quand la méthode est virtuelle
Messages postés
57
Date d'inscription
vendredi 21 mai 2004
Statut
Membre
Dernière intervention
28 juillet 2006

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.
Messages postés
57
Date d'inscription
vendredi 21 mai 2004
Statut
Membre
Dernière intervention
28 juillet 2006

Oui en revanche ce qui est etrange cest que ca ne marchait pas uniquement pour les fonctions virtuelles...
Messages postés
252
Date d'inscription
vendredi 10 juin 2005
Statut
Membre
Dernière intervention
5 septembre 2006
1
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.
Messages postés
57
Date d'inscription
vendredi 21 mai 2004
Statut
Membre
Dernière intervention
28 juillet 2006

Merci beaucoup pour cette precision.
Thomas.
Messages postés
2070
Date d'inscription
mardi 22 avril 2003
Statut
Membre
Dernière intervention
3 juillet 2006
8
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...