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 :

Tester la validité d'un pointeur


Sujet :

C++

  1. #1
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    577
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 577
    Par défaut Tester la validité d'un pointeur
    Re-Bonjour,

    J'ai un pointeur sur un objet de la classe CMyCall dont j'aimerais tester la validité au cours de l'exécution du programme.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    void f1(CMyCall* pCall)
    {
       f2(pCall);
    }
     
    void f2(CMyCall* pCall)
    {
      ...
      //Lance un thread avec pCall en paramètre
      AfxBeginThread( (AFX_THREADPROC) _ThreadProc, (LPVOID) pCall );
     
    }
    Or dans ce thread, j'aimerais tester pCall avant de faire des actions dessus (answer, speak, drop)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    UINT thread(LPVOID par)
    {
      CMyCall*  pCall = (CMyCall*)par;
     
      if(pCall) pCall->Answer();
      if(pCall) pCall->Speak();
      if(pCall) pCall->Drop();
    }
    Donc tout le problème est que pCall peut être détruit ailleurs en cours de programme, et ensuite mis à NULL, lorsque l'appel a été raccroché par l'autre partie par exemple.
    La fonction qui se charge de ça, fait :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    pCall->Deallocate();
    pCall = NULL;
    Quelle est la solution pour avoir accès au test if(pCall) dans mon thread, car là tel que j'ai fait le pointeur passé n'est pas averti de la mise à NULL ?

    @+

  2. #2
    Membre éclairé
    Avatar de buzzkaido
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juillet 2004
    Messages
    821
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2004
    Messages : 821
    Par défaut
    Une solution, c'est d'utiliser les smart_pointer de boost

    Enfin, je crois que c'est fait pour ça

  3. #3
    Membre éclairé
    Avatar de buzzkaido
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juillet 2004
    Messages
    821
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2004
    Messages : 821
    Par défaut
    Euh, ben sinon, au lieu de detruire ton objet par un delete, tu peut le detruire par un appel à

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    void deleteMyCall(CMyCall &(*pCall))
    {
        delete (&pCall);
        pCall = NULL;
    }
    Que tu definirais comme une fonction "globale"

    Je suis pas sûr du tout de la syntaxe, mais l'idée c'est de passer par référence un pointeur à la fonction. Celle-ci detruit l'objet pointé et met à NULL la variable référencée.

  4. #4
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Par défaut
    CMyCall &(*pCall))
    Tu voulais dire CMyCall*& pCall ?

  5. #5
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    577
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 577
    Par défaut
    salut,
    merci pour ton idée, je ne vois pas en quoi cela change quoique ce soit, puisque'au final tu ne fais que pCall = NULL ...
    Je l'ai essayé et, à moins d'avoir mal fait, cela ne change rien.

    En effet si l'appel en cours est perdu, et donc que je désalloue l'appel et le met à NULL, je vois bien dans mon thread que mon pCall reste non NULL, mais pointe vers une zone mémoire libérée.

    Je sais bien que ceci est normal car en fin de compte je ne peux pas demander à tous les pointeurs référençant un objet de dévenir NULL lorsque je détruits cet objet et que je mets son pointeurs à NULL.

    Mais je cherche une solution ...

  6. #6
    Expert confirmé

    Homme Profil pro
    pdg
    Inscrit en
    Juin 2003
    Messages
    5 756
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : pdg

    Informations forums :
    Inscription : Juin 2003
    Messages : 5 756
    Billets dans le blog
    3
    Par défaut
    Il te faut passer par un objet supplémentaire spécialisé dans la gestion de la vie de ton CMyCall. On t'a conseillé les pointeurs intelligents de boost, c'est un bon conseil.
    http://c.developpez.com/faq/cpp/?pag...OST_shared_ptr
    Combiné a un weak_ptr, tu peux obtenir l'effet recherché (tester la validité d'un pointeur), avec plus de sécurité (empecher la destruction de l'objet pendant qu'il est utilisé, car rien dans ton exemple n'empeche deleteMyCall() de détruire ton objet alors que pCall->Answer() est en cours d'exécution)

  7. #7
    Expert confirmé
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 292
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 292
    Par défaut
    En général, je jongle avec deux approches que je mélange parfois selon les accès:

    - Dabord ceux qui surveillent le pointeur qui peut disparaitre sont des observateurs qui vont recevoir des notifications comme quoi le pointeur peut être invalidé.

    - Ensuite, de plus en plus j'utilise des LockPtr plus ou moins évolués suivant les cas. Ils s'occupent d'encapsuler la donnée pouvant être détruite depuis n'importe quel thread. Ce qui me permet de ne pas altérer le pointeur (typiquement le détuire) tant qu'une opération est en cours dessus. Je m'inspire pour cela d'un article d'Andrei Alexandrescu relatif à une utilisation originale du mot clé mutable pour éliminer les courses -- l'article se retrouve depuis son site.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  8. #8
    Membre éprouvé
    Avatar de NiamorH
    Inscrit en
    Juin 2002
    Messages
    1 309
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 1 309
    Par défaut
    Si tu passe un pointeur de pointeur a ton thread, et que dans le programme tu fais pointeur = 0; le pointeur de pointeur pointera vers zero. C'est gagné.

  9. #9
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    577
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 577
    Par défaut
    Merci pour vos réponses,

    Aurelien : je vais étudier les pointeurs de boost, que je ne connais pas du tout encore. De plus, quand tu dis "(empecher la destruction de l'objet pendant qu'il est utilisé, car rien dans ton exemple n'empeche deleteMyCall() de détruire ton objet alors que pCall->Answer() est en cours d'exécution)", tu as tout a fait raison

    Luc : concernant ton premier point, existe-t-il un DP sur les observateurs ou des exemples de mise en oeuvre ?
    Ensuite, je vais m'informer de traitement proposé à base de LockPtr, mais sachant que ce que je souhaite, en plus de pouvoir l'utiliser protégé par Lock, c'est savoir s'il a été détruit ou pas, et donc s'il est bien valide.

    Niamorh : je ne peux pas faire ce que tu dis, car la fonction qui passe le pointeur au thread n'est pas celle qui le crée et qui le détruit. Il y a eu avant ça diverses affectations de pointeurs depuis la création de l'objet initial, et elle passe au thread un pointeur le référençant. Donc si je suis ton raisonnement, je passe un pointeur référençant un pointeur qui n'est pas celui que je mets à NULL ailleurs. Donc à mon avis, cela ne peut pas fonctionner.


    Une autre solution pourrait consister, avant de vouloir s'en servir de repartir systématiquement à sa recherche pour savoir si on le retrouve encore dans les piles des couches + basses (donc s'il n'a pas encore été détruit), mais cela devient vite trés fastidieux.


    PS : En tout cas, j'a bien l'impression que c'est pas si simple que ça ...

  10. #10
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 394
    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 394
    Par défaut
    Qu'il y ait pointeur intelligent ou non, il sera indispensable de faire du verrouillage: Comme l'a dit Aurelien (accent?), sans verrouillage l'objet pourrait être désalloué avant entre le moment où le thread vérifie et celui où il l'utilise.

    Au passage:
    Citation Envoyé par olive_le_malin
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    AfxBeginThread( (AFX_THREADPROC) _ThreadProc, (LPVOID) pCall );
    Le premier cast est très mauvais : Si ça ne compile pas sans la cast, c'est 80% de chances de plantage.
    Tu dois supprimer ton cast et corriger la signature de _ThreadProc au besoin.
    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.

  11. #11
    Membre éprouvé
    Avatar de NiamorH
    Inscrit en
    Juin 2002
    Messages
    1 309
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 1 309
    Par défaut
    C'est certain, une synchronisation avant d'utiliser le pointeur est necessaire si tu fais un delete quelque part ou pour tout acces non thread safe.

    Mais je maintiens que si tout tes threads possèdent un pointeur vers le pointeur principal, il n'y a plus de problèmes pour savoir quand ton pointeur n'est plus valide. Suffit de ne passer a chaque fois que du Objet** entre les interlocuteurs. C'est pas très contraignant à recoder.

  12. #12
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 394
    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 394
    Par défaut
    Danc ce genre de cas, je serais plutôt pour centraliser le pointeur lui-même dans une structure et passer partour un pointeur vers la structure en question: Cela permet d'éviter de se balader avec des ** partout.

    Ou encore, passer un objet qui renferme le pointeur de pointeur ou le pointeur de la structure contenant le pointeur. Les Smart Pointers de boost appartiennent à la catagorie "objet qui renferme le pointeur de la structure contenant le pointeur"...
    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 éprouvé
    Avatar de NiamorH
    Inscrit en
    Juin 2002
    Messages
    1 309
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 1 309
    Par défaut
    Ca à l'air pas mal alors.

    Il faudra que je me renseigne la dessus. J'ai toujours tendance à vouloir n'utiliser que le minimum de libs souvent au détriment de la complexité de mon code.

  14. #14
    Expert confirmé

    Homme Profil pro
    pdg
    Inscrit en
    Juin 2003
    Messages
    5 756
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : pdg

    Informations forums :
    Inscription : Juin 2003
    Messages : 5 756
    Billets dans le blog
    3
    Par défaut
    Citation Envoyé par NiamorH
    Mais je maintiens que si tout tes threads possèdent un pointeur vers le pointeur principal, il n'y a plus de problèmes pour savoir quand ton pointeur n'est plus valide.
    La gestion de la concurrence est plus complexe qu'il n'y parrait.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if(pCall) pCall->Answer();
    ton thread peut etre interrompu juste (ou peu) apres que le test ait réussit, et, pas de bol, l'autre thread peut détruire pCall a ce moment la. Résultat : Answer va etre exécuté sur un objet détruit...

    A partir du moment ou une ressource est partagée, il faut un mécanisme commun de gestion de la vie de cette ressource, sinon n'importe qui peut détruire la ressource pendant qu'un autre l'utilise.

  15. #15
    Membre éprouvé
    Avatar de NiamorH
    Inscrit en
    Juin 2002
    Messages
    1 309
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 1 309
    Par défaut
    non c'est certain cela ne remplace pas des synchronisations, mais je sais qu'à l'interieur des sections critiques j'aime bien faire des test if(m_truc) et etre sur que si mon objet n'est pas 0 alors il est toujours valide plutot que de faire appel a autre chose pour le determiner.

  16. #16
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 394
    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 394
    Par défaut
    Dans ce cas, il peut être intéressant de mettre la section critique dans la même structure que le pointeur...
    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.

  17. #17
    Expert confirmé

    Homme Profil pro
    pdg
    Inscrit en
    Juin 2003
    Messages
    5 756
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : pdg

    Informations forums :
    Inscription : Juin 2003
    Messages : 5 756
    Billets dans le blog
    3
    Par défaut
    Et c'est ce que fait boost...

  18. #18
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    577
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 577
    Par défaut
    Bon, ben je vois bien qu'il va falloir que je m'interesse de plus prés à boost ...

    ça sera l'occasion !

  19. #19
    Expert confirmé
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 292
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 292
    Par défaut
    Les observateurs correspondent bien à un pattern... éponyme.


    Quant à boost, je doute que cela soit suffisant. Il y a bien un lock, mais au niveau des références comptées. Nullement au niveau des opérations exécutées : il ne faudrait pas que l'objet soit détruit durant l'exécution d'une de ses opérations.

    Sans parler que cela ne sera pas d'une grande utilité quand on manipule des tâches suicidaires (elles reçoivent le message "va mourrir" et puis se terminent seules dans leur coin (i.e. dans leur(s) thread(s) une fois prêtes).


    Le test "if (p) p->operation();" résume bien des choses. Après avoir testé p, il ne faut surtout pas qu'il soit détruit avant le début de l'opération, ni même pendant.

    Grossièrement, je définis des proxies qui à leur création lockent la ressource (si disponible), et ensuite forwardent (sans mourrir) l'opération à l'objet protégé. À leur destruction, le lock est libéré. La destruction de la ressource s'appuyant sur le même lock -- que le lock soit réentrant, R/W, ... peu importe.
    Le proxy étant employé comme une variable locale sur la pile ne pouvant mourrir que de fin de portée.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  20. #20
    Expert confirmé

    Homme Profil pro
    pdg
    Inscrit en
    Juin 2003
    Messages
    5 756
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : pdg

    Informations forums :
    Inscription : Juin 2003
    Messages : 5 756
    Billets dans le blog
    3
    Par défaut
    Si on n'utilise que des pointeurs intelligents, comment l'objet peut-il etre détruit durant l'exécution d'une de ses opérations ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    weak_ptr<CMyCall> pCall;
     
    if(shared_ptr<CMyCall> p = pCall.lock())
    {
        p->Answer();
    }
    par contre, pour passer le weak_ptr en parametre au thread, c'est pas evident.

Discussions similaires

  1. [VB.NET] Comment tester la validité d'une date ?
    Par Zefree dans le forum ASP.NET
    Réponses: 5
    Dernier message: 15/12/2012, 15h49
  2. Comment tester la validité d'une adresse mail
    Par jmoez dans le forum Oracle
    Réponses: 1
    Dernier message: 19/04/2006, 13h00
  3. [pointeur] Tester la validité
    Par Luffy Duck dans le forum C++
    Réponses: 13
    Dernier message: 16/01/2006, 17h39
  4. Comment tester la validité d'un répertoire?
    Par Gabrielly dans le forum MFC
    Réponses: 5
    Dernier message: 25/02/2005, 11h13
  5. [web] tester la validiter d'une URL
    Par zebiloute dans le forum Web
    Réponses: 4
    Dernier message: 25/11/2002, 16h51

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