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 :

Codeguard erreur sur destructeur


Sujet :

C++Builder

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    229
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 229
    Par défaut Codeguard erreur sur destructeur
    Bonjour,

    je passe codeguard sur mon appli et j'ai une erreur que j'ai du mal à comprendre.
    Mon appli est constituée d'une dll et d'un exe.
    Ma dll exporte la fonction suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    vector<TEventData> __stdcall mLgetFaults()
    TEventData est une classe à moi.
    La partie exe récupère le vector, tout se passe bien à l’exécution, mais si je compile avec codeguard, il me signale une erreur sur le destructeur de TEventData (qui ne fait rien vu que cette classe ne contient que de types simples) :
    Bad parameter in process: MonAppli.exe(6480) - c:\program files\embarcadero\rad studio\8.0\include\dinkumware\xmemory#129
    A bad object (0x34F79E0) has been passed to the function.
    0x006909BC Call to delete(0x03507A80)
    ...................
    0x0040B38B - src\GenericData\EventData.h#45
    .............................
    à cette ligne j'ai le code suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    	~TEventData()
    	{
    	};
    Il passe donc 2 fois dans le destructeur ce qui me parait normal en fait (une fois pour la création des TEventData dans l'exe, une fois pour la création dans la dll), mais ça ne doit pas être le cas puisque codeguard me sort une erreur...
    J'avoue que je ne comprends pas trop...

    merci d'avance pour vos suggestions d'explication
    Pascale38

  2. #2
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 081
    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 081
    Par défaut
    En C++Builder 2007, mon CodeGuard me fait souvent des VA à la fermeture du projet, je crois que c'est au moment du déchargement des Packages

    Cela a été amélioré en XE2

    Sinon attention, ne partage pas d'objet entre EXE et DLL, évite de créer d'un côté et libérer de l'autre côté !

    Tu n'échange tout de même pas un vector directement ?
    Ta DLL ne pourra être utilisé qu'avec uniquement la version de ton compilateur (un vector de C++Builder6 n'aura peut-être pas la même gueule mémoire que celui de C++BuilderXE2, et je ne parle même pas des autres compilateurs C++)

    En plus, ça ne fait pas des copies dans tous les sens ça ?
    Tu devrais plutôt faire une fonction respectant les conventions WinAPI

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    BOOL __stdcall mLgetFaults(TEventData* Buf, int& BufCount);
    Buf est alloué du côté appelant, il indique le nombre d'élement possible par BufCount (en nombre d'item) ou un BufSize en octet

    cela renvoi un code d'erreur pour signaler un Buf trop petit
    Typiquement, si tu fournis Buf NULL, la fonction calcule BufCount, permettant d'allouer la mémoire !
    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

  3. #3
    Membre Expert
    Avatar de DjmSoftware
    Homme Profil pro
    Responsable de compte
    Inscrit en
    Mars 2002
    Messages
    1 044
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Responsable de compte
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 044
    Billets dans le blog
    1
    Par défaut
    ce point est documenté sur MSN
    voici le lien
    http://support.microsoft.com/kb/172396/fr
    cdlt
    vous trouverez mes tutoriels à l'adresse suivante: http://djmsoftware.developpez.com/
    je vous en souhaite une excellente lecture ...

    A lire : Les règles du forum

  4. #4
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    229
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 229
    Par défaut
    Salut ShaiLeTroll,

    bon j'avais pas envie de m'embêter avec des pointeurs, je sais ça fait des copies, mais bon mon vector fait 24 max donc c'est pas énorme non plus.
    Mais bon merci pour l'info, je ne savais pas que c'était incompatible entre version de compilo !!
    Sinon j'utilise XE, alors comment savoir si c'est un problème codeguard ou non ?

    Utiliser
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    BOOL __stdcall mLgetFaults(TEventData* Buf, int& BufCount);
    j'avoue que je trouve ça super lourd !! Allouer un Buf sans savoir sa taille avec une valeur au hasard... beurk
    Bon ceci dit j'ai testé, j'alloue mon buf à 24 dans l'appelant (vu que là j'ai la chance de savoir que c'est le max), je fais le delete dans l'appelant et j'obtiens exactement la même erreur codeguard... sur le delete et sur le destructeur de TEventData...

    Donc DjmSoftware, merci pour ton lien, mais il semblerait qu'il n'y ait aucun rapport avec le fait que j'utilise un conteneur de la STL.

    Pascale38

  5. #5
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 081
    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 081
    Par défaut
    Citation Envoyé par Pascale38 Voir le message
    j'avoue que je trouve ça super lourd !! Allouer un Buf sans savoir sa taille avec une valeur au hasard... beurk
    C'est pas faux, d'où DEUX Appels comme je l'avais expliqué dans ma réponse !
    Un Appel mLgetFaults(NULL, var);il rempli var avec ce qu'il faut allouer puis mLgetFaults(buf, var);Typique des API Windows !

    Tu peux aussi faire une liste chainée avec une fonction mLgetFaultsFirst(Buf) et mLgetFaultsNext(CurBuf, NextBuf)Fonctionnement du TreeView je crois !

    Je préfère utiliser des interfaces, ainsi, la mémoire est alloué côté DLL, tu peux avoir une propriétés Count\Items, facile à utiliser, puis une méthode pour nettoyer !
    Ainsi ma DLL n'a que deux trois Exports, dont l'un est une Factory, ensuite tout le reste c'est POO à fond !

    J'utilise aussi bien des Interface C++ (class abstraitre pure) que des DelphiInterface (TInterfacedObject, GUID et Supports ...)
    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

  6. #6
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    229
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 229
    Par défaut
    Not possible pour 2 appels :
    En fait le "tableau" est construit dynamiquement à chaque appel, entre 2 appels il peut très bien contenir +ou- d'éléments...

    Les autres solutions, surement très bien, toujours un peu lourdes à mon goût...
    Tout ça pour échanger un tableau...

    Ceci dit mon problème de base avec codeguard reste le même :
    c'est donc codeguard qui bug ???

    merci en tout cas pour toutes tes pistes !!!
    Pascale38

  7. #7
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 081
    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 081
    Par défaut
    Ce n'est pas vraiment CodeGuard qui bug mais qui ne comprend pas que l'on libère un objet alloué dans l'espace mémoire d'un processus A dans un module B
    Cela vient plutot de Windows et la gestion mémoire entre EXE et DLL

    C'est pour cela qu'il existait ShareMem en Delphi
    La RTL dynamique doit être aussi un aspect de cela !

    Tant que ta DLL reste une utilisation interne et non utilisable par des logiciels tiers, tu peux te permettre ta méthode

    Je te conseille de suivre la méthode de l'article de DjmSoftware !
    Un petit pointeur ça ne fait pas de mal !

    ton code actuel
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    vector<TEventData> __stdcall mLgetFaults();
    remplace le par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    typedef vector<TEventData> TEventDataVector;
    typedef TEventDataVector* PEventDataVector;
     
    PEventDataVector __stdcall mLgetFaults();
    void__stdcall mLFreeFaults(PEventDataVector Vector);
    Ainsi, tu échanges un pointeur créé par la DLL
    Il faudra juste libéré manuellement !
    CodeGuard sera content de voir que Allocation et Libération sont effectué du même côté !

    Je ne fais du C++ que depuis un an, en Delphi les habitudes ne sont pas les mêmes mais pour ton cas un code façon RAII serait idéal

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    struct TEventDataReader
    {
      PEventDataVector Items;
     
      TEventDataReader()
      {
         Items = mLgetFaults();
      }
     
      ~TEventDataReader()
      {
        mLFreeFaults(Items);
      }
    }
    Dans ton juste en déclarant un TEventDataReader cela appèle la DLL, et en le libére implicitement


    Tu peux aussi différé la lecture, si tu ne veux pas que dès que l'instanciation se produit cela appelle la DLL, par exemple si tu veux en faire un membre de classe

    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
    struct TEventDataReader
    {
      PEventDataVector Items;
     
      TEventDataReader() : Items(NULL) {};
     
      int ReadItems();
      {
         Items = mLgetFaults();
         return Items->size(): 
      }
     
      ~TEventDataReader()
      {
        if (Items)
          mLFreeFaults(Items);
      }
    }
    le code d'appel étant très simple

    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
    void MaFonction()
    {
      ...
     
      TEventDataReader Reader; 
      if (Reader.ReadItems() > 0)
      {
        for (TEventDataVector::iterator it = Reader.Items->begin(); it != Reader.Items->end(); ++it)
        {
          *it ... 
        }
      }
     
      // libération automatique à la fin du bloc
    }
    le typedef simplifie l'utilisation du type vector, cela donne un code plus rigoureux !
    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

Discussions similaires

  1. Erreur sur une fonction avec des paramètres
    Par Elois dans le forum PostgreSQL
    Réponses: 2
    Dernier message: 05/05/2004, 21h00
  2. [VBS] Erreur sur "AddWindowsPrinterConnection"
    Par Admin dans le forum VBScript
    Réponses: 5
    Dernier message: 27/03/2004, 16h15
  3. Erreur sur serveur lié
    Par k-lendos dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 18/03/2004, 15h21
  4. []Erreur sur second emploi collection binding
    Par jacma dans le forum VB 6 et antérieur
    Réponses: 2
    Dernier message: 08/03/2004, 18h02
  5. Erreur sur le TNSListener après installation de 9iAS
    Par Patmane dans le forum Installation
    Réponses: 4
    Dernier message: 04/02/2004, 11h16

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