IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C++ Discussion :

Callback et erreur mémoire


Sujet :

C++

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    92
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 92
    Par défaut Callback et erreur mémoire
    Bonjour à tous,

    J'ai un petit problème lors de la réalisation d'un projet. Histoire d'expliquer un peu comment ça marche : j'ai un programme qui appelle un activeX. Jusque là tout va bien.
    Mais ça se complique. Une callback est implémentée dans le programme appelant. Elle est ensuite appelée à partir de l'activeX. Tout ça fonctionne mais j'ai un problème : ça plante (erreur mémoire) lorsque je sors de la callback.

    Voici un bout de code pour comprendre :

    Programme appelant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
     
    void maclasse::fonction()
    {
    wrapperActiveX.RegisterEventCallback(hdl, EventCallback, this); 
    wrapperActiveX.openURL(hdl, url);
    }
     
    void maclasse::EventCallback(HANDLE hdl, EVENT_TYPE p_event, void* params, void* paramsD) //statique
    {
       maclasse* pThis = static_cast<maclasse*>(pvAppData);
       pThis->eventCallback(hdl, p_event, params);
    }
     
    void maclasse::eventCallback(HANDLE hdl, EVENT_TYPE p_event, void* params)
    {
    ...//code fonctionnel
    }
    Du côté du source de l'OCX, ça donne ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    int OCX::openURL(HANDLE hdl, char* url)
    {	
        return DLLFunction_open( hdl, url);
    }
     
    bool DLLFunction_open(HANDLE hdl, char* url)
    {
       ...
       if (m_pEventCallback) //m_pEventCallback = EventCallback lors de l'appel à RegisterEventCallback  
    	m_pEventCallback(ToHandle(), event, params, paramsD); //event = OpeningURL
       ...
    }
    Donc pour résumer :

    - Je registre ma callback en appelant une fonction de l'OCX en lui passant notamment le pointeur de fonction correspondant à ma callback (EventCallback).
    - J'appelle ensuite une autre fonction de l'OCX (opeNURL) qui elle-même appelle la callback :
    m_pEventCallback(ToHandle(), event, params, paramsD);
    Je vois bien au débugger que l'on passe dans la callback.
    - Une fois le traitement terminé, ça plante à la sortie de :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    void maclasse::EventCallback(HANDLE hdl, EVENT_TYPE p_event, void* params, void* paramsD) //statique
    {
       maclasse* pThis = static_cast<maclasse*>(pvAppData);
       pThis->EventCallback(hdl, p_event, params);
    }
    Au débugguer c'est après l'acolade de sortie que ça plante. Du côté OCX, je vois que je passe l'appel à la callback mais lorsque ça plante, je ne suis là aussi pas sorti de la fonction (DLLFunction_open) appellant la callback. Par contre le code suivant l'appel est exécuté sans problème.

    Quelqu'un a t-il déjà rencontré un problème comme celui-là? J'ai l'impression que c'est un problème de pile mais je vois pas d'où il pourrait venir...

    Merci d'avance!

  2. #2
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Par défaut
    Cela ressemble effectivement à un problème de pile.

    Pour tester, je changerai la méthode d'appel de la fonction statique
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void maclasse::EventCallback(HANDLE hdl, EVENT_TYPE p_event, void* params, void* paramsD)
    en rajoutant un __stdcall devant

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void __stdcall maclasse::EventCallback(HANDLE hdl, EVENT_TYPE p_event, void* params, void* paramsD)
    Et si cela ne marche pas essaye avec les autres méthodes d'appel (c'est un peu empirique et pas très déterministe comme méthode mais j'ai pas mieux)

    regarde ici pour plus d'info (en anglais)
    Raymond
    Vous souhaitez participer à la rubrique Réseaux ? Contactez-moi

    Cafuro Cafuro est un outil SNMP dont le but est d'aider les administrateurs système et réseau à configurer leurs équipements SNMP réseau.
    e-verbe Un logiciel de conjugaison des verbes de la langue française.

    Ma page personnelle sur DVP
    .

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    92
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 92
    Par défaut
    Wow ça semble marcher . Merci beaucoup

    J'ai lu le lien mais j'avoue ne pas y comprendre grand chose...quelle est la différence entre ma fonction et celle utilisant la méthode d'appel stdcall?

    Je comprends bien qu'il y a quelque chose avec la pile mais je ne vois pas pourquoi ça ne fonctionnait pas avant...Si j'ai bien compris, c'est maintenant la fonction appelée qui est responsable de dépiler les paramètres. Avant celà c'était la fonction appelante (désolé j'ai un peu de mal avec la pile)?

  4. #4
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Par défaut
    Bon, je suis bien content que ton problème soit résolu.

    Maintenant, les explications (en admettant que la méthode d'appel implicite par défaut de ton compilateur soit __cdecl)

    La grosse différence se situe au niveau de qui doit nettoyer la pile après un appel de fonction :
    • __cdecl : Calling function pops the arguments from the stack, c'est l'appelant qui nettoie
    • __stdcall : Called function pops its own arguments from the stack, c'est l'appelé qui nettoie


    Si l'appelant et l'appelé ne s'entendent pas sur qui a la responsabilité du nettoyage de la pile, tu obteins ce que tu as eu, une corruption de pile
    Raymond
    Vous souhaitez participer à la rubrique Réseaux ? Contactez-moi

    Cafuro Cafuro est un outil SNMP dont le but est d'aider les administrateurs système et réseau à configurer leurs équipements SNMP réseau.
    e-verbe Un logiciel de conjugaison des verbes de la langue française.

    Ma page personnelle sur DVP
    .

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    92
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 92
    Par défaut
    Merci, maintenant j'ai bien compris
    Au niveau compilateur. Si j'ai deux projets, les deux sont compilés sous VS 2003 pour l'un et 2005 pour l'autre (avec compilo Intel en plus).
    Y'aurait-il une différence entre les deux? Le compilo Intel y serait-il alors pour quelque chose?
    Peut-on voir la méthode d'appel utilisée quelque part (dans les propriétés du projet...)?

  6. #6
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Citation Envoyé par CodeCRC Voir le message
    Peut-on voir la méthode d'appel utilisée quelque part (dans les propriétés du projet...)?
    Bonjour,
    Le comportement par défaut peut être positionné dans les options de compilations (calling conventions (/Gd, /Gr, et /Gz pour Visual). J'imagine que pour le compilo Intel ça doit être la même chose. En revanche, je n'en connait pas les valeurs par défaut pour Intel. Pour visual, c'est /Gd : __cdecl.

  7. #7
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    92
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 92
    Par défaut
    Effectivement, c'est bien _cdecl pour les deux environnements Visual.
    Je n'arrive pas à accéder à l'information pour le compilo Intel par contre.

    Si ce n'est pas le compilateur Intel qui n'a pas la même convention, pourquoi le fait de rajouter _stdcall fait fonctionner le logciel alors que mes deux environnements ont la même convention??

  8. #8
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Par défaut
    Connais tu laz convention d'appel utilisée pour compiler ton activeX

    Autre chose, peut être que même si tu connais la convention d'appel utilisée pour générer ton ActiveX, cette convention est modifiée temporairement parce que c'est un appel callback

    (Je donne des pistes, je ne suis sûr de rien)
    Raymond
    Vous souhaitez participer à la rubrique Réseaux ? Contactez-moi

    Cafuro Cafuro est un outil SNMP dont le but est d'aider les administrateurs système et réseau à configurer leurs équipements SNMP réseau.
    e-verbe Un logiciel de conjugaison des verbes de la langue française.

    Ma page personnelle sur DVP
    .

  9. #9
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    92
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 92
    Par défaut
    Citation Envoyé par ram-0000 Voir le message
    Connais tu laz convention d'appel utilisée pour compiler ton activeX

    Autre chose, peut être que même si tu connais la convention d'appel utilisée pour générer ton ActiveX, cette convention est modifiée temporairement parce que c'est un appel callback

    (Je donne des pistes, je ne suis sûr de rien)
    Ben je n'arrive pas à voir les propriétés du compilateur Intel mais ça doit surement être ça.

  10. #10
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    92
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 92
    Par défaut
    En continuant à dev, je me suis aperçu que le problème n'est pas complètement résolu en réalité...

    Ca fonctionne mais en sortie de la fonction :

    m_pEventCallback(ToHandle(), event, params, paramsD);

    Un pointeur utilisé pour appeler la callback (de type IPlayerEventSink) et que je souhaite pouvoir utiliser plus tard doit être écrasé en sortie de callback. En gros, avant d'appeler la callback, je teste l'existence du pointeur, s'il existe, j'appelle la callback mais en sortie, il n'a plus de valeur...
    Il me semble que c'est encore un problème de convention d'appel...

  11. #11
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    92
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 92
    Par défaut
    C'est résolu. Et en résolvant j'ai compris le pourquoi du _stdcall.
    Toutes les fonctions de ma DLL sont définies avec un :

    Qui est lui même une référence vers "__stdcall". Donc si j'ai bien compris à partir de mon programme appellant l'OCX qui encapsule la fameuse DLL, toutes les fonctions de la DLL utilisée doivent être préfixées de "__stdcall"?

  12. #12
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 398
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 398
    Par défaut
    Oui.
    C'est la convention d'appel "standard" de Windows. Si tu ne préfixe pas la fonction de __stdcall, sa convention d'appel sera par défaut la convention d'appel "C" (__cdecl), qui ne sert pratiquement que pour le C et le C++.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  13. #13
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    92
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 92
    Par défaut
    Tout fonctionne bien maintenant, merci

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Message d'erreur : "Mémoire insuffisante [..]"
    Par mcroz dans le forum Access
    Réponses: 8
    Dernier message: 01/03/2007, 17h14
  2. Erreur mémoire insuffisante
    Par jpp81 dans le forum VB 6 et antérieur
    Réponses: 2
    Dernier message: 27/01/2007, 07h31
  3. [MFC] Erreur mémoire
    Par leMehdi dans le forum MFC
    Réponses: 8
    Dernier message: 26/01/2006, 16h09
  4. message d'erreur "Mémoire insuffisante"
    Par jakouz dans le forum Langage
    Réponses: 3
    Dernier message: 25/10/2005, 14h41
  5. Réponses: 1
    Dernier message: 16/05/2004, 17h56

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo