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++Builder Discussion :

problème avec free et delete


Sujet :

C++Builder

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre habitué
    Inscrit en
    Décembre 2004
    Messages
    12
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 12
    Par défaut problème avec free et delete
    Bonjour à tous
    je suis entrain d'utiliser un programme que j'ai développé en utilisant l'environnement c++builder. j'utilise des listes doublement chaînées, j'alloue avec malloc et je libère avec free. après un nombre assez important d'alloc/desalloc, un message d'erreur surgit:
    "le projet simulateur3.exe a provoqué une classe d'exception EAccessViolation avec le message 'Violation d'accès à l'adresse ... dans le module 'BORNDMM.DLL'. lecture de l'adresse.... processus stoppé.. "
    J'ai pas pu savoir d'où provient cette erreur car tout parait normal lorsque j'ai utilisé le pas à pas mais j'ai pu localiser quel est l'objet ( par son identifiant ) qui en le libérant provoque cet arrêt et donc j'ai modifié le programme de sorte qu'il ignore l'instruction de désallocation de cet objet, alors le programme ne se plante pas à la rencontre de cet objet, il avance dans l’exécution mais il se plante de la même façon en rencontrant l'instruction de désallocation d'un autre objet.
    il est à remarquer que même en utilisant les instruction new et delete au lieu de malloc et free le même problème se produit avec les mêmes objets et que même si j'ai lancé l’exécution plusieurs fois, le programme se plante avec les mêmes objets.
    y a t il quelqu'un qui peut m'aider et merci d'avance

  2. #2
    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
    Bonjour
    (Sauf s'il existe un cas particulier de C++ Builder que je connais pas), en C++ les allocations utilisent new/delete et pas malloc/free.

    Pour ton problème, cela ressemble fortement à des trois erreurs 'classiques' lors de la manipulation des pointeurs :
    => double libération du même pointeur ;
    => débordement dans l'écriture dans la zone allouée ;
    => mix entre new[]/delete ou new/delete[].

    Les solutions :
    std::vector plutôt que des allocations dynamiques explicites pour les tableaux
    boost/std/tr1::shared_ptr pour les pointeurs sur des instances d'objets.

  3. #3
    Membre habitué
    Inscrit en
    Décembre 2004
    Messages
    12
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 12
    Par défaut
    Bonjour et merci beaucoup 3DArchi pour ta réponse. J'ai modifié tout le code en utilisant les fonctions new et delete (bienque les autres malloc et free me posaient pas de problème avant, mais tout d'un coup j'ai eu le problème dont j'ai parlé dans ce forum) mais malheureusement le problème demeure le même. Tu m'as proposé boost/std/tr1::shared_ptr, merci beaucoup, à vrai dire c'est la première fois que j'entends parler de ça, je vais essayer de voir comment ça marche et s'il y a possibilité de l'utiliser dans mon programme.
    merci

  4. #4
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 048
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 048
    Par défaut
    Tu devrais commencer par protéger la libération, justement, avec les TObject un delete sur un pointeur NULL ne provoque rien
    A vérifier sur un pointeur de struct, mais je te conseille avant chaque libération de tester la nullité du pointeur et de l'affecter à NULL comme ceci

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    {
      TypePointeurALibérer Tmp = PtrALibérer;
      PtrALibérer = NULL;
      delete Tmp;
    }
    En Delphi, typer le pointeur permet de gérer les AnsiString et Array dynamique (une libération en void* laisserait trainer ces pointeurs invisibles)
    En C++, je suppose que cela doit permettre de gérer aussi les objets en allocation statique ? je ne suis pas encore tout à fait au point la dessus !

    Depuis moins d'un an, je suis passé de D7 à BCB2007, j'utilise souvent le vector ou map au lieu d'une TList, qui n'existait pas encore en template\generics à cette époque !

    Perso, 'BORLNDMM.DLL'(et non 'BORNDMM.DLL') et ShareMem, je ne suis pas Fan en Delphi, mais cela semble plus courant en C++Builder
    En C++, il semble ne pas exister FastShareMem\SimpleShareMem ...

    Est-ce que ton programme partage des Pointeurs ou objets comme AnsiString avec une DLL ?
    Si oui, veille à allouer et libérer du même côté !
    Si ton exécutable ne partagera pas d'objet avec une DLL, tu pense retirer "RTL Dynamique" et construire SANS les paquets d'exécution, ton EXE sera plus gros mais sera aussi plus facile à déployer !
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  5. #5
    Membre habitué
    Inscrit en
    Décembre 2004
    Messages
    12
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 12
    Par défaut
    Merci Beaucoup pour ta réponse qui paraît m'avoir résolu le problème. J'ai fait comme tu m'as indiqué: affectation du pointeur null suivi du delete, ça a marché pour un premier test du programme, j'espère que ça sera pareil pour d'autre test. Mais, j'ai une interrogation: d'habitude on fait un delete puis on affecte null (d'ailleurs c'est ce que je fais dans mon programme), comment explique t on que affecter null avant le delete est plus "sécurisé"? est ce que je dois précéder tous mes delete par une affectation à null dans mon programme?
    merci beaucoup pour ton aide très précieuse.

  6. #6
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 048
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 048
    Par défaut
    La plupart de mes delete comme cela

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    delete Obj;
    Obj = NULL;
    normalement un destructeur ne pas produit d'exception !
    un delete, ne devrait jamais échoué, une erreur indique un mauvais code !

    Disons qu'a part en multi-thread et une libération qui ne serait pas protégé par une SectionCritique, l'affectation anticipée évite une double libération !
    C'est moche !

    J'ai quelques libérations avec l'affectation à NULL avant le delete, une paranoïa d'une exception durant le destructeur ... et le risque que le destructeur se produise plusieurs fois !
    C'est juste que je nettoie très mal les std::map<Ident, Type*>, je les parcours, je fais mon delete sur chaque it*, et je clear d'un coup après la boucle
    Je n'utilise pas de erase à chaque itération (comme on le ferait avec std::vector), faudrait que je trouve une manière plus propre !

    En Delphi 7, les templates n'existent pas donc je ne poserais pas la question, héritage de la TList, typage de Items, et un Notify pour libérer lors du delete via un Clear()
    En fait, en Delphi, j'utilise bcp plus d'objet, en C++, je triche souvent avec des typedef struct interne à mes classes.

    En réalité, faudrait faire un try catch (tracer l'erreur, ne pas la masquer complètement), si il y a des éléments qui provoque des exceptions durant un destructeur

    FreeAndNil du Delphi c'est

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    procedure FreeAndNil(var Obj);
    var
      Temp: TObject;
    begin
      Temp := TObject(Obj);
      Pointer(Obj) := nil;
      Temp.Free;
    end;
    Si il l'on fait comme cal, ce n'est pas un hazard !

    En deplhi, un objet membre d'une collection souvent envoie une notification à la liste,
    un TControl par exemple lorsqu'on le libère indique à son Parent qui le retire de sa propriété Controls[]

    Sinon, lorsque le Parent y accedera, tu auras une violation d'accès !

    Tu utilises une liste-double chainée, typiquement, tu as donc deux fois le pointeur, le Next et le Prior !
    Tu as peut-être un conflit à ce sujet
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  7. #7
    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
    La bonne façon de gérer une ressource (comme un pointeur) reste l'enveloppe RAII comme les pointeurs intelligents.

    Au plus simple cela pourrait être :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    template<class T>
    struct ptr_unique
    {
    ptr_unique(T *arg = new T):ptr(arg){}
    ~ptr_unique(){delete ptr;}
    T& operator*() {return *ptr;}
    T const& operator*() const{return *ptr;}
    T* operator->() {return ptr;}
    T const* operator->() const {return ptr;}
    private:
    T *ptr;
    ptr_unique(ptr_unique const&); // = delete, à ne pas definir
    ptr_unique&operator=(ptr_unique const&); // = delete, à ne pas definir
    };

Discussions similaires

  1. problème avec les trigger delete
    Par mb10 dans le forum Administration
    Réponses: 3
    Dernier message: 25/01/2012, 16h46
  2. Problème avec la requête delete
    Par totoAussi dans le forum Requêtes
    Réponses: 3
    Dernier message: 29/08/2011, 12h33
  3. problème avec free
    Par nhella22 dans le forum Débuter
    Réponses: 15
    Dernier message: 28/05/2011, 17h06
  4. Problème avec free()
    Par Invité dans le forum Débuter
    Réponses: 3
    Dernier message: 03/05/2011, 15h14
  5. Problème avec trigger for delete
    Par tornade69 dans le forum MS SQL Server
    Réponses: 5
    Dernier message: 07/10/2008, 09h37

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