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

MFC Discussion :

Pb de pointeur mal détruit


Sujet :

MFC

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  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 Pb de pointeur mal détruit
    Bonjour,
    j'utilise dans un prog une liste chainée où chacun des maillons est alloué avec new, desalloué avec delete.
    Mon probleme : si dans le thread n°1 je travaille sur un maillon, et que dans le thread n°2 je détruits ce maillon (en le mettant à NULL apres le delete), je me retrouve dans le thread n°1 avec un maillon non nul, mais détruit, et du coup je ne peux pas faire if(p != NULL)

    En gros :

    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
    18
    19
    20
     
    thread 1 :
    csPile.Lock();
    info = p->info;
    csPile.Unlock();
     
    thread 2 :
    csPile.Lock();
    delete p;
    p = NULL;
    csPile.Unlock();
     
    thread 1 :
    csPile.Lock();
    if(p != NULL)  //ça passe
    info = p->info;  //ça plante
    csPile.Lock();
     
     
    Merci par avance

  2. #2
    Rédacteur
    Avatar de farscape
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    9 055
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

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

    Informations forums :
    Inscription : Novembre 2003
    Messages : 9 055
    Par défaut
    salut a tout reorganiser tu peux utiliser ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    // example for AfxIsMemoryBlock
    CAge* pcage = new CAge( 21 ); // CAge is derived from CObject.
    ASSERT( AfxIsMemoryBlock( pcage, sizeof( CAge ) ) )
    AfxIsMemoryBlock te diras si l'adresse allouer est valide.

  3. #3
    tut
    tut est déconnecté
    Membre éclairé
    Avatar de tut
    Inscrit en
    Juillet 2002
    Messages
    373
    Détails du profil
    Informations forums :
    Inscription : Juillet 2002
    Messages : 373
    Par défaut
    slt,
    t'aurais pas un problème de synchronisation ?
    normalement, si tu fais un Lock() ta structure de données doit être protégée, et tu dois être sûr que tant qu'elle est lockée, personne n'y a accès, donc si tu fais un delete et p=NULL, normalement, un thread qui veut y avoir accès doit être en attente de la libération de la ressource...
    Si ton mécanisme de synchronisation est bien fait, le problème ne devrait pas se poser.

  4. #4
    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
    la liste chainee est bien protégée.
    C'est simplement que dans le thread 1, je fais le unlock() pour laisser la main a un autre thread, et puis je la re-lock() pour faire du traitement dessus.
    Et c'est dans ce laps de temps (entre le Unlock() et le lock()) où le 2nd thread intervient sur la liste chainée (et il en a le droit puisqu'elle n'est pas lockée), et qu'il delete le maillon. C'est ensuite que dans le thread 1 (apres le lock) ce maillon n'est pas nul, mais quand même détruit.

    Alors qu'il soit détruit, c'est normal !! Mais qu'il ne soit pas nul (alors que je le met à NULL dans le thread 2), ça je comprends pas !!

  5. #5
    Rédacteur
    Avatar de farscape
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    9 055
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

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

    Informations forums :
    Inscription : Novembre 2003
    Messages : 9 055
    Par défaut
    comme c'est pas coherent soit ton lock echoue soit c''est pas la meme variable.


  6. #6
    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
    AfxIsMemoryBlock plante ("user breakpoint caller from code ...") !!!

  7. #7
    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
    je t'assure qu'il n'y a pas de pb de lock() / Unlock().
    Quand à la variable c'est la même, puisqu'en travaillant au debugger, je vois trés bien que l'adresse du maillon p est bien la même dans le thread 1 et dans le thread 2.

    Je ne comprends donc pas





    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
    18
    thread 1 : 
    csPile.Lock(); 
    info = p->info; //OK
    csPile.Unlock(); 
     
    Sleep(10000); //C'est pendant ce temps que le thread2 accede à la liste
     
    csPile.Lock(); 
    if(p != NULL)  //ça passe (ça ne devrait pas !!!!!)
        info = p->info;  //ça plante 
    csPile.Unlock(); 
     
     
    thread 2 : 
    csPile.Lock(); 
    delete p; 
    p = NULL; 
    csPile.Unlock();

  8. #8
    Rédacteur
    Avatar de abelman
    Inscrit en
    Février 2003
    Messages
    1 106
    Détails du profil
    Informations forums :
    Inscription : Février 2003
    Messages : 1 106
    Par défaut
    Hum,
    csPile est donc un objet CCritcalSection. (OK ?)
    Quelle est sa portée ? C'est bien une variable globale ?

  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
    oui

  10. #10
    Membre éclairé Avatar de bilb0t
    Profil pro
    Inscrit en
    Décembre 2003
    Messages
    378
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : Belgique

    Informations forums :
    Inscription : Décembre 2003
    Messages : 378
    Par défaut
    C'est pas pasque tu détruit un object et que tu mets son pointeur à NULL que tout les pointeurs le référençant vont être à NULL !

  11. #11
    Rédacteur
    Avatar de abelman
    Inscrit en
    Février 2003
    Messages
    1 106
    Détails du profil
    Informations forums :
    Inscription : Février 2003
    Messages : 1 106
    Par défaut
    Citation Envoyé par bilb0t
    C'est pas pasque tu détruit un object et que tu mets son pointeur à NULL que tout les pointeurs le référençant vont être à NULL !
    Ben si normalement. Ou alors je t'ai mal compris

  12. #12
    Rédacteur
    Avatar de farscape
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    9 055
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

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

    Informations forums :
    Inscription : Novembre 2003
    Messages : 9 055
    Par défaut
    c'est incompréhensible ton pb il faudrait voir le code en entier
    c'est pas possible ça doit etre gros comme une maison!
    entre autre l'endroit ou sont declarées les variables etc...

  13. #13
    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
    Alors pour solutionner mon probleme, je suis passé par un pointeur de pointeur.
    Je crois que ça rejoint ce que disait bilbOt.

    J'ai fait (sachant que *pp du thread1 <-> p du thread 2)
    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
    18
    19
    20
     
    thread 1 : 
    pile** pp = NULL;
    csPile.Lock(); 
    info = (*pp)->info; //OK 
    csPile.Unlock(); 
     
    Sleep(10000); //C'est pendant ce temps que le thread2 accede à la liste 
     
    csPile.Lock(); 
    if(*pp != NULL)  //et là c'est bon
        info = (*pp)->info;
    csPile.Unlock(); 
     
     
    thread 2 : 
    csPile.Lock(); 
    delete p; 
    p = NULL; 
    csPile.Unlock();
    Vous voyez une incorrection ou qqch d'incohérent ?

  14. #14
    mat.M
    Invité(e)
    Par défaut
    Bonjour,
    pourquoi utiliser Sleep ??? Il ne faut pas utiliser Sleep , j'ai fait la même remarque sur le forum C++ Builder .
    Comme l'a suggéré mes prédecesseurs , c'est ( on s'en doute ) , un problème de synchronisation.
    Mais par pitié ne pas utiliser Sleep c'est ça qui occasionne des blocages.
    Pourquoi il faut absolument éviter Sleep : pour la bonne et unique raison que tu espères attendre mettons 10 sec soient 10000ms.
    Le problème est : quel est le temps d'exécution des processus indépendants qui sont crées ? Y-a-t-il une bonne synchronisation ?
    Et comment va tourner ton programme dans 3 ans sur une machine 2 fois plus rapide ?

    A chaud comme cela difficile d'apporter une solution ,il faut peut-être utiliser des Event ou autres .

  15. #15
    mat.M
    Invité(e)
    Par défaut
    MSDN:

    You have to be careful when using Sleep and code that directly or indirectly creates windows. If a thread creates any windows, it must process messages. Message broadcasts are sent to all windows in the system. If you have a thread that uses Sleep with infinite delay, the system will deadlock. Two examples of code that indirectly creates windows are DDE and COM CoInitialize. Therefore, if you have a thread that creates windows, use MsgWaitForMultipleObjects or MsgWaitForMultipleObjectsEx, rather than Sleep.

  16. #16
    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
    Il n'y a pas de blocage !!
    c'est simplement que si mon pointeur est détruit et remis à NULL dans le thread 2, il n'est pas NULL dans le thread 1.
    A force d'essayer des trucs, j'en suis venu à l'utilisation d'un pointeur de pointeur passé au thread 1, et seul un pointeur de pointeur dans le thread 1 voit la mise à NULL dans le thread 2.

    Mais je vous assure qu'il n'y a aucun probleme de blocage et de synchronisation.
    Concernant le Sleep utilisé, il est vrai que ce n'est pas trés Catholique, mais c'est plus pour l'exemple que pour autre chose. En fait c'est pendant ces 10 secondes (j'aurais pu mettre 60 secondes ou même plus), qu'à la main (par une touche de raccourci incluse dans mon programme) je lance le thread 2 qui accede à la pile, et supprime un maillon !!

    Alors, voyez-vous une autre manière de tester ce pointeur deleté et mis à NULL ?

  17. #17
    mat.M
    Invité(e)
    Par défaut
    Ok d'accord il n'ya pas de blocage mais qu'en est-il sur une autre machine dans un contexte d'exécution différent ?
    Il faut trouver une autre méthode

  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
    En gros voici quel était mon probleme :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    char* p = new char[32];     //p vaut 0x00421ae0
    strcpy(p, "le pointreur");     //*p = "le pointeur"
     
    char* p2 = p;                    //p2 vaut 0x00421ae0, *p2 = "le pointeur"
     
    delete p;                          //liberation de la memoire prise par p
                                           //avec *p = *p2 = "YYYYYYYYYYYYYYYY"
    p = NULL;                         //p vaut 0x00000000
     
    //MAIS p2 vaut toujours 0x00421ae0

    La seule maniere de voir au travers de p2 que p vaut NULL est de faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    char* p = new char[32];     //p vaut 0x00421ae0
    strcpy(p, "le pointreur");     //*p = "le pointeur"
     
    char** p2 = &p;                //*p2 = p = 0x00421ae0, **p2 = "le pointeur"
     
    delete p;                          //liberation de la memoire prise par p
                                           //avec *p = **p2 = "YYYYYYYYYYYYYYYY"
    p = NULL;                         //p = *p2 = 0x00000000
    Donc je me suis bien fait avoir en pensant que lorsque l'on détruit un pointeur et qu'on le met à NULL, on va aussi mettre à NULL tous les pointeurs le référençant (ce qui soulignait bilbOt, donc attention abelman !)

  19. #19
    Rédacteur
    Avatar de abelman
    Inscrit en
    Février 2003
    Messages
    1 106
    Détails du profil
    Informations forums :
    Inscription : Février 2003
    Messages : 1 106
    Par défaut
    Ok Je vais tester cela

  20. #20
    Rédacteur
    Avatar de farscape
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    9 055
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

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

    Informations forums :
    Inscription : Novembre 2003
    Messages : 9 055
    Par défaut
    Moi ça me semble tout a fait normal c'est le piége typique que l'on retrouve
    dans une classe avec des données membres de type pointeur quand on a pas fait un constructeur de copie et d'affectation lorsque l'un des 2 mécanismes est évoqué on a 2 objets avec des pointeurs qui adressent la même mémoire
    Lorsque l'un des 2 objets se détruit et fait son ménage l'autre objet a des pointeurs qui adressent du vent
    C’est bien pour ça qu'au début je t'ai demande si on parlait de la même variable p dans 2 thread apparemment non.
    Et pas un autre variable nommée p .

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. set<Pointeur*> mal trié
    Par laflak dans le forum SL & STL
    Réponses: 14
    Dernier message: 21/12/2008, 23h31
  2. pointeur DNS détruit
    Par olivanto dans le forum Windows Serveur
    Réponses: 2
    Dernier message: 23/10/2007, 16h32
  3. Réponses: 27
    Dernier message: 24/05/2007, 23h29
  4. djgpp et pointeurs far -2
    Par elvivo dans le forum Autres éditeurs
    Réponses: 16
    Dernier message: 29/07/2002, 22h43
  5. djgpp et pointeurs far
    Par elvivo dans le forum C
    Réponses: 2
    Dernier message: 13/07/2002, 00h44

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