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 :

problème libération mémoire après une DLL


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éprouvé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    1 299
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 299
    Par défaut problème libération mémoire après une DLL
    Bonjour,

    j'ai fait un programme en C sous Visual C++ 6.0. Tout se passe bien lors de l'exécution. Lors de la libération de la mémoire j'appelle la fonction suivante :

    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
     
    void DestroyResultatFit(ResultatFit ** rfit)
    {
      if(*rfit != NULL)
      {
        DestroyGRC(&(*rfit)->grc);
        DestroyGIF(&(*rfit)->gif);
        DestroyGSF(&(*rfit)->gsf);
        DestroyPLC(&(*rfit)->plc);
        DestroyGRF(&(*rfit)->grf);
        DestroyDCN(&(*rfit)->dcn);
        DestroyExtrapolation(&(*rfit)->extra);
    	DestroyDFLU(&(*rfit)->dflu);
    	DestroyCyclesGSFGRCGRF(&(*rfit)->cycles);
    	DestroyGIFDELI(&(*rfit)->gifdeli);
    	DestroyPLCDELI(&(*rfit)->plcdeli);
        FREE(*rfit);
      }
    }
    A la sortie de cette fonction, rfit == NULL. Dans le debugger, pas à pas, tous les champs sont bien remis à NULL. Lorsque je sors de cette fonction, rfit->gif (idem pour tous les champs), le debugger m'affiche

    gif CXX0030: Error: expression cannot be evaluated
    pourquoi ?

    Maintenant, lorsque ma fonction "coeur de calcul" est appelée via une DLL (j'ai fait un autre projet qui me crée ma dll et au lieu d'appeler la fonction j'appelle la dll), le programme plante lors de la libération de la mémoire.

    Pouvez-vous m'aider s'il vous plait ? Je vous envoie qq structures. Si je comprends pour le champs rfit->gif, je comprendrais pour tout le reste.

    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
    21
    22
    23
    24
    25
    26
    27
    28
    29
     
    typedef struct
    {
      double coeff[GIF_MAX_NBELEM];
      double ted;
      double teg;
      double etr;
      double em;
    } GIF;
     
    GIF * CreateGIF(double coeff[GIF_MAX_NBELEM],double ted,double teg,double etr,double em)
    {
      int i;
      GIF * gif=malloc(sizeof(*gif));
      if(gif == NULL) return NULL;
     
      for(i=0;i<GIF_MAX_NBELEM;i++) gif->coeff[i]=coeff[i];
      gif->ted=ted;
      gif->teg=teg;
      gif->etr=etr;
      gif->em=em;
     
      return gif;
    }
     
    void DestroyGIF(GIF ** gif)
    {
      FREE(*gif);
    }
    Merci d'avance

  2. #2
    Membre émérite
    Inscrit en
    Juillet 2005
    Messages
    512
    Détails du profil
    Informations forums :
    Inscription : Juillet 2005
    Messages : 512
    Par défaut
    Pour liberer une zone memoire alloué avec malloc on utilise free et non pas FREE.
    (FREE connait pas !)

  3. #3
    Membre éprouvé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    1 299
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 299
    Par défaut
    salut,

    oups, j'ai oublié de préciser ma macro

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    #define FREE(p) \
    do              \
    {               \
      free(p);      \
      p=NULL;       \
    }               \
    while(0)

  4. #4
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par salseropom Voir le message
    salut,

    oups, j'ai oublié de préciser ma macro

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    #define FREE(p) \
    do              \
    {               \
      free(p);      \
      p=NULL;       \
    }               \
    while(0)
    Ce qui est une façon compliquée d'écrire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    #define FREE(p) free(p), (p) = NULL

  5. #5
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par salseropom Voir le message
    A la sortie de cette fonction, rfit == NULL. Dans le debugger, pas à pas, tous les champs sont bien remis à NULL. Lorsque je sors de cette fonction, rfit->gif <...>
    Tu cherches à déréférencer un pointeur NULL ?
    Maintenant, lorsque ma fonction "coeur de calcul" est appelée via une DLL (j'ai fait un autre projet qui me crée ma dll et au lieu d'appeler la fonction j'appelle la dll), le programme plante lors de la libération de la mémoire.

    Pouvez-vous m'aider s'il vous plait ? Je vous envoie qq structures. Si je comprends pour le champs rfit->gif, je comprendrais pour tout le reste.
    Ce code
    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
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
     
    #include <stdlib.h>
    #include <string.h>
     
    #define FREE(p) free(p), (p) = NULL
     
    #define GIF_MAX_NBELEM 10
     
    typedef struct
    {
       double coeff[GIF_MAX_NBELEM];
       double ted;
       double teg;
       double etr;
       double em;
    }
    GIF;
     
    GIF *CreateGIF (double coeff[GIF_MAX_NBELEM], double ted, double teg,
                    double etr, double em)
    {
     
       GIF *gif = malloc (sizeof *gif);
       if (gif != NULL)
       {
          memcpy (gif->coeff, coeff, sizeof gif->coeff);
     
          gif->ted = ted;
          gif->teg = teg;
          gif->etr = etr;
          gif->em = em;
       }
       return gif;
    }
     
    void DestroyGIF (GIF ** gif)
    {
       FREE (*gif);
    }
    est correct. Le problème est ailleurs.

  6. #6
    Membre éprouvé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    1 299
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 299
    Par défaut
    Re-bonjour,
    j'ai réussi (en partie) à reproduire l'erreur que j'obtiens dans un code "plus court". Je dis "en partie" car en mode Release il n'y a aucun problème mais en mode Debug j'ai comme erreur : "Debug assertion failed - file dbgheap.c line 1044".

    J'ai cette même erreur dans mon programme (qui plante aussi en mode Release).

    Dans le fichier main1.c je crée ma dll et dans le fichier main2.c j'appelle non plus la fonction DoubleToto() mais la DLL qui contient cette fonction.

    Pourquoi ai-je une telle erreur en mode Debug ? Je rappelle que je travaille sous Visual Studio C++ 6.0

    Merci d'avance

    Voici le fichier main1.c
    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
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
     
    #include<stdlib.h>
    #include<stdio.h>
     
    #define N 3
     
    typedef struct
    {
      double a;
      double b;
      double tab[N];
    } Toto;
     
    Toto * CreateToto(double a,double b,double * tab)
    {
      int i;
     
      Toto * toto=malloc(sizeof(*toto));
      if(toto != NULL)
      {
        toto->a=a;
    	toto->b=b;
    	for(i=0;i<N;i++) toto->tab[i]=tab[i];
      }
      return toto;
    }
     
    void DestroyToto(Toto ** toto)
    {
      free(*toto); *toto=NULL;
    }
     
    void PrintToto(Toto * toto)
    {
       int i;
       printf("%f\t%f\n",toto->a,toto->b);
       for(i=0;i<N;i++) printf("%f\t",toto->tab[i]);
       printf("\n");
    }
     
    __declspec(dllexport) Toto * DoubleToto(Toto * toto)
    {
      int i;
      Toto * toto2=malloc(sizeof(*toto2));
      if(toto2!=NULL)
      {
        toto2->a=2.*toto->a;
        toto2->b=2.*toto->b;
    	for(i=0;i<N;i++) toto2->tab[i]=toto->tab[i]*2.;
      }
      return toto2;
    }
     
     
    int main(void)
    {
      double a,b,tab[]={1.,4.,5};
      Toto * toto=NULL, * toto2=NULL;
      a=1.;
      b=2.;
     
      toto=CreateToto(a,b,tab);
      PrintToto(toto);
      toto2=DoubleToto(toto);
      PrintToto(toto2);
      DestroyToto(&toto);
      DestroyToto(&toto2);
     
      return 0;
    }
    et voici le fichier main2.c qui appelle la dll

    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
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
     
    #include<stdlib.h>
    #include<stdio.h>
     
    #define N 3
     
    typedef struct
    {
      double a;
      double b;
      double tab[N];
    } Toto;
     
    Toto * CreateToto(double a,double b,double * tab)
    {
      int i;
     
      Toto * toto=malloc(sizeof(*toto));
      if(toto != NULL)
      {
        toto->a=a;
    	toto->b=b;
    	for(i=0;i<N;i++) toto->tab[i]=tab[i];
      }
      return toto;
    }
     
    void DestroyToto(Toto ** toto)
    {
      free(*toto); *toto=NULL;
    }
     
    void PrintToto(Toto * toto)
    {
       int i;
       printf("%f\t%f\n",toto->a,toto->b);
       for(i=0;i<N;i++) printf("%f\t",toto->tab[i]);
       printf("\n");
    }
     
    extern Toto * __cdecl DoubleToto(Toto *);
     
     
    int main(void)
    {
      double a,b,tab[]={1.,4.,5};
      Toto * toto=NULL, * toto2=NULL;
      a=1.;
      b=2.;
     
      toto=CreateToto(a,b,tab);
      PrintToto(toto);
      toto2=DoubleToto(toto);
      PrintToto(toto2);
      DestroyToto(&toto);
      DestroyToto(&toto2);
     
      return 0;
    }

  7. #7
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par salseropom Voir le message
    Dans le fichier main1.c je crée ma dll et dans le fichier main2.c j'appelle non plus la fonction DoubleToto() mais la DLL qui contient cette fonction.
    Le fichier main1.c n'est pas un fichier de DLL correct. Il n'y a pas de main() dans une DLL. Il y'a par contre un point d'entrée obligatoire à fournir (DllMain()). Lire la doc de MSDN.
    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
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
     
    // a sample exported function
    void DLL_EXPORT SomeFunction(const LPCSTR sometext)
    {
        MessageBoxA(0, sometext, "DLL Message", MB_OK | MB_ICONINFORMATION);
    }
     
    BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
    {
        switch (fdwReason)
        {
            case DLL_PROCESS_ATTACH:
                // attach to process
                // return FALSE to fail DLL load
                break;
     
            case DLL_PROCESS_DETACH:
                // detach from process
                break;
     
            case DLL_THREAD_ATTACH:
                // attach to thread
                break;
     
            case DLL_THREAD_DETACH:
                // detach from thread
                break;
        }
        return TRUE; // succesful
    }
    D'autre part attention au vocabulaire. on n'"appelle" pas une DLL. On appelle éventuellement une fonction de la DLL. Encore faut-il que le lien dynamique ait été réalisé. As-tu lié le .lib de ta DLL a ton application ?

  8. #8
    Membre éprouvé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    1 299
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 299
    Par défaut
    Citation Envoyé par Emmanuel Delahaye Voir le message
    Le fichier main1.c n'est pas un fichier de DLL correct. Il n'y a pas de main() dans une DLL. Il y'a par contre 2 points d'entrée obligatoires à fournir. Lire la doc de MSDN.

    D'autre part attention au vocabulaire. on n'"appelle" pas une DLL. On appelle éventuellement une fonction de la DLL. Encore faut-il que le lien dynamique ait été réalisé. As-tu lié le .lib de ta DLL a ton application ?
    oui, je me suis planté dans ce post. Dans mon projet visual je n'ai pas de main pour faire ma DLL.
    Sinon, j'ai bien réalisé le lien dynamique de ma DLL. Dans mon projet où j'appelle une fonction de ma DLL, tout le programme tourne. Ce n'est qu'à la fin du main (donc je suis sorti de la fonction appelée dans la DLL), lors de la libération mémoire, que ça plante...

    En revanche, en mode exécutable, la libération de la mémoire s'effectue correctement. Bien entendu, c'est le même code pour libérer la mémoire.

    Je me renseigne sur le point d'entrée de la DLL.

  9. #9
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    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 395
    Par défaut
    Citation Envoyé par salseropom Voir le message
    en mode Debug j'ai comme erreur : "Debug assertion failed - file dbgheap.c line 1044".

    Ce qui a été alloué par un module doit être libéré par le même module. Une transgression de cette règle est sûrement la source de ton erreur.
    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.

  10. #10
    Membre éprouvé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    1 299
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 299
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    Ce qui a été alloué par un module doit être libéré par le même module. Un transgression de cette règle est sûrement la source de ton erreur.

    Effectivement, cela peut répondre à mon problème.

    voici un organigramme de mon code :

    int main(void)
    {
    1) je lis mes inputs contenues dans différents fichiers texte
    2) coeur de calcul : ici j'appelle une fonction de ma DLL. Cette fonction appelle d'autres fonctions qui ne sont pas dans ma DLL. Dans le coeur de calcul j'alloue de la mémoire
    3) post-traitement : j'écris sur le disque dur tout plein de résultats
    4) je libère la mémoire (allouée lors de la lecture des inputs et dans la fonction appelée par la DLL). C'est dans cette partie qu'apparait le problème

    return 0;
    }
    Mais cela me cause un autre soucis : si je comprends bien, toute la mémoire allouée lors de l'exécution du coeur de calcul (qui appelle une fonction de ma DLL et cette fonction appelle plein d'autres fonctions qui ne sont pas dans la DLL) doit être libérée à la sortie du coeur de calcul.

    Donc comment écrire sur le disque dur mes sorties (j'ai un peu peur de poser une question bête...) si j'ai libérée ma mémoire. Je dois avoir un problème de conception alors. En tous les cas, l'organigramme doit être respecté :

    1) pré-traitement
    2) traitement : appel du coeur de calcul
    3) écriture des résultats
    4) libération de la mémoire

    et je dois fournir mon coeur de calcul sous forme de DLL

    Merci encore de votre aide

  11. #11
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    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 395
    Par défaut
    Citation Envoyé par salseropom Voir le message
    si je comprends bien, toute la mémoire allouée lors de l'exécution du coeur de calcul (qui appelle une fonction de ma DLL et cette fonction appelle plein d'autres fonctions qui ne sont pas dans la DLL) doit être libérée à la sortie du coeur de calcul.
    Ou à tout moment, du moment que c'est une fonction de la DLL qui le fait.
    Tu peux même exporter une fonction de la DLL exprès pour ça...
    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.

  12. #12
    Membre éprouvé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    1 299
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 299
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    Ou à tout moment, du moment que c'est une fonction de la DLL qui le fait.
    Tu peux même exporter une fonction de la DLL exprès pour ça...
    Salut, c'est ce que je viens de faire. j'ai inclus ma fonction DestroyMemory() dans la DLL.

    Merci beaucoup de votre aide !

    En revanche, je n'ai pas bien compris ce que disais Emmanuel quant aux 2 points d'accroche... je vais continuer à chercher

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

Discussions similaires

  1. [MFC] Problèmes d'inclusion d'une DLL
    Par CaptnB dans le forum MFC
    Réponses: 1
    Dernier message: 12/05/2006, 18h01
  2. [VB] Problème de chargement d'une DLL
    Par Elijha dans le forum Windows Forms
    Réponses: 3
    Dernier message: 10/05/2006, 09h24
  3. Réponses: 2
    Dernier message: 10/02/2006, 14h46
  4. Problème de création d'une dll...
    Par adrien954 dans le forum C++Builder
    Réponses: 4
    Dernier message: 21/10/2005, 10h46
  5. Problème mémoire avec une dll par chargement dynamique
    Par widze19 dans le forum C++Builder
    Réponses: 6
    Dernier message: 15/12/2003, 13h20

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