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 :

Erreur avec la commande free


Sujet :

C

  1. #1
    Membre régulier Avatar de be_tnt
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    312
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2005
    Messages : 312
    Points : 84
    Points
    84
    Par défaut Erreur avec la commande free
    Voilà je sèche sur un coredump généré par la commande free (fin du code ci-dessous). Si je le mets en commentaire, pas de problème. Sinon le programme crashe

    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
     
    result = (char *)malloc(10*sizeof(char));
     if ( (result == NULL ) {
          // Not enough memory so stop execution and return failed
          strncpy(failureMessage, "Authentication failed. Not enought memory.\n", FAILURE_MSG_SIZE -1);
          failureMessage[FAILURE_MSG_SIZE] = (char)0;
          return QIPAUTHCALLOUT_FAIL;
       }
     
       result = getenv("AUTHCALLOUTDEBUG");
       if ( result != NULL ) {
          // check the value of result
          if ( strcmp(result,"ON") == 0 ) {
             // tracing is ON
             DEBUG = 1;
          }
       }
       /* Free up the memory space allocated to the result variable */
       free(result);

  2. #2
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 381
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 381
    Points : 41 582
    Points
    41 582
    Par défaut
    1°) Jamais de cast au retour de malloc() : Inutile en C, et pas de malloc() du tout en C++

    2°)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    result = getenv("AUTHCALLOUTDEBUG");
    getenv() retourne l'adresse d'une chaîne statique, supposée invariable (son type de retour devrait être const)
    Bref, pas de free() sur un retour de getenv().

    3°) Au passage, la mémoire allouée par malloc() est leakée.

  3. #3
    Expert éminent sénior

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Points : 11 877
    Points
    11 877
    Par défaut
    Bonjour,

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    result = (char *)malloc(10*sizeof(char));
    - Pas de cast du malloc.
    - sizeof(char) == 1 donc inutile
    - Si tu as une taille fixe, pourquoi faire un malloc, une allocation statique suffit amplement.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
     if ( (result == NULL ) {
          // Not enough memory so stop execution and return failed
          strncpy(failureMessage, "Authentication failed. Not enought memory.\n", FAILURE_MSG_SIZE -1);
          failureMessage[FAILURE_MSG_SIZE] = (char)0;
          return QIPAUTHCALLOUT_FAIL;
       }
    strncpy, si tu donnes une taille assez grande met le '\0' tout seul... Ce n'est pas la peine de le faire à la main... Autant utiliser strcpy pour ce que tu fais...

    result = getenv("AUTHCALLOUTDEBUG");
    Depuis quand est-ce qu'on alloue une zone mémoire pour écraser le pointeur avec une autre adresse mémoire? Du coup, t'as perdu la première zone...

    Donc c'est logique que ton programme plante...
    Jc

  4. #4
    Membre régulier Avatar de be_tnt
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    312
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2005
    Messages : 312
    Points : 84
    Points
    84
    Par défaut
    Merci Medinoc.

    que veux tu dire par leakée??

  5. #5
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 381
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 381
    Points : 41 582
    Points
    41 582
    Par défaut
    Citation Envoyé par fearyourself
    strncpy, si tu donnes une taille assez grande met le '\0' tout seul... Ce n'est pas la peine de le faire à la main... Autant utiliser strcpy pour ce que tu fais...
    strncpy() est faite pour marcher SANS qu'on donne une taille assez grande.
    Et là, le zéro terminal dépend (hélas!) de l'implémentation : le standard exige peut-être le \0, mais en tout cas, le strncpy() de la CRT Microsoft ne le met pas.
    Citation Envoyé par MSDN
    If count is less than or equal to the length of strSource, a null character is not appended automatically to the copied string
    Donc, si, le failureMessage[FAILURE_MSG_SIZE] = (char)0; doit rester (à supposer que failureMessage soit de taille FAILURE_MSG_SIZE+1, sinon, il y a un -1 à rajouter)

  6. #6
    Membre du Club
    Inscrit en
    Mai 2003
    Messages
    99
    Détails du profil
    Informations forums :
    Inscription : Mai 2003
    Messages : 99
    Points : 66
    Points
    66
    Par défaut
    Bonjour,


    c'est dur de dire
    1°) Jamais de cast au retour de malloc() :
    J'avais lu que l'on pouvait parfois caster, pour garder une compatibilité avec d'anciens compilateurs pré-ANSI ...

  7. #7
    Membre régulier Avatar de be_tnt
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    312
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2005
    Messages : 312
    Points : 84
    Points
    84
    Par défaut
    Citation Envoyé par fearyourself
    Bonjour,

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    result = (char *)malloc(10*sizeof(char));
    - Pas de cast du malloc.
    - sizeof(char) == 1 donc inutile
    - Si tu as une taille fixe, pourquoi faire un malloc, une allocation statique suffit amplement.
    donc si je te suis bein, je devrais plutôt faire:
    Citation Envoyé par fearyourself

    Depuis quand est-ce qu'on alloue une zone mémoire pour écraser le pointeur avec une autre adresse mémoire? Du coup, t'as perdu la première zone...

    Donc c'est logique que ton programme plante...
    hummm sorry je suis plutôt débutane en C avec un gros problème avec les pointeurs

  8. #8
    Expert éminent sénior

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Points : 11 877
    Points
    11 877
    Par défaut
    Citation Envoyé par ankou82
    Bonjour,

    c'est dur de dire

    J'avais lu que l'on pouvait parfois caster, pour garder une compatibilité avec d'anciens compilateurs pré-ANSI ...
    Le jour où tu compileras avec un compilateur pré-ANSI, met des casts...

    donc si je te suis bien, je devrais plutôt faire:
    Oui



    Jc

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

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par be_tnt
    Merci Medinoc.

    que veux tu dire par leakée??
    leak = fuite
    memory leak = fuite mémoire (mémoire non libérée)

    Voic le rapport de mon gestionnaire de mémoire après exécution de 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
    40
    41
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    #define FAILURE_MSG_SIZE 128
     
    enum
    {
       OK,
       QIPAUTHCALLOUT_FAIL,
       dummy
    };
     
    int main()
    {
       int DEBUG = 0;
       char failureMessage[FAILURE_MSG_SIZE];
       char *result = (char *)malloc(10 * sizeof(char));
       if ( result == NULL )
       {
          // Not enough memory so stop execution and return failed
          strncpy(failureMessage, "Authentication failed. Not enought memory.\n", FAILURE_MSG_SIZE - 1);
          failureMessage[FAILURE_MSG_SIZE] = (char)0;
          return QIPAUTHCALLOUT_FAIL;
       }
     
       result = getenv("AUTHCALLOUTDEBUG");
       if ( result != NULL )
       {
          // check the value of result
          if ( strcmp(result, "ON") == 0 )
          {
             // tracing is ON
             DEBUG = 1;
          }
       }
       /* Free up the memory space allocated to the result variable */
       free(result);
       return 0;
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    FRMWRK.DBG_SYSALLOC=1
    SYSALLOC Overload (85 rec)
    SYSALLOC Successful initialization: 85 records available
    SYSALLOC min=4294967295 max=4294967295 delta=0
    SYSALLOC Err: Not-matched list:
    SYSALLOC Bloc 003D24F0 (10 bytes) malloc'ed at line 18 of 'main.c' not freed
    SYSALLOC Released Memory
    FRMWRK.Termine
     
    Press ENTER to continue.
    En fait ton code est beucoup trop compliqué. Ceci suffit :
    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
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    int main()
    {
       int DEBUG = 0;
     
       char *result = getenv("AUTHCALLOUTDEBUG");
       if ( result != NULL )
       {
          // check the value of result
          if ( strcmp(result, "ON") == 0 )
          {
             // tracing is ON
             DEBUG = 1;
          }
       }
       return 0;
    }

  10. #10
    Membre régulier Avatar de be_tnt
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    312
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2005
    Messages : 312
    Points : 84
    Points
    84
    Par défaut
    huh du coup:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     result = getenv(MYVAR);
    ne marche plus (error: incompatible types in assignment)

  11. #11
    Membre régulier Avatar de be_tnt
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    312
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2005
    Messages : 312
    Points : 84
    Points
    84
    Par défaut
    euh tu peux expliquer l'output de ta commande?

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

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par be_tnt
    euh tu peux expliquer l'output de ta commande?
    La ligne importante est celle-ci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SYSALLOC Bloc 003D24F0 (10 bytes) malloc'ed at line 18 of 'main.c' not freed
    Faut que je traduise ?

  13. #13
    Membre régulier Avatar de be_tnt
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    312
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2005
    Messages : 312
    Points : 84
    Points
    84
    Par défaut
    Citation Envoyé par Emmanuel Delahaye
    La ligne importante est celle-ci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SYSALLOC Bloc 003D24F0 (10 bytes) malloc'ed at line 18 of 'main.c' not freed
    Faut que je traduise ?
    Donc si je comprend bien, la mémoire réservée par le malloc exécuté en line 18 n'a pas été libérée. Je croyais que quand on utilisait des pointeurs, il fallait faire un malloc et donc ensuite un free

  14. #14
    Expert éminent sénior

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Points : 11 877
    Points
    11 877
    Par défaut
    Citation Envoyé par be_tnt
    huh du coup:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     result = getenv(MYVAR);
    ne marche plus (error: incompatible types in assignment)
    Logique, je disais que pour une allocation de taille fixe, une allocation statique était plus adaptée. Dans ton problème aucune allocation est nécessaire. Seul un pointeur l'est.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
       char *result;
       result = getenv("AUTHCALLOUTDEBUG");
    Jc

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

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par be_tnt
    Donc si je comprend bien, la mémoire réservée par le malloc exécuté en line 18 n'a pas été libérée. Je croyais que quand on utilisait des pointeurs, il fallait faire un malloc et donc ensuite un free
    Comme tu as remplacé la valeur du pointeur par une autre,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
       char *result = (char *)malloc(10 * sizeof(char));
    <...>
       result = getenv("AUTHCALLOUTDEBUG");
    la valeur originale est perdue et le free() ne libère pas la bonne zone (comportement indéfini).

    Mon gestionnaire d'allocations mémoire constate que le bloc n'a pas été libéré, c'est tout. Il n'en donne pas les raisons.

    En fait, comme déjà expliqué, il n'y a pas besoin de malloc(), à moins qu'on veuille conserver la valeur... Dans ce cas, strdup() est certainement plus adapté. cette fonction n'est pas standard C, mais POSIX.1, donc très portable. Elle est facile à implémenter si besoin est...

    Et je rappelle qu'une affectation de chaine se fait avec strcpy() en C...

  16. #16
    Membre régulier Avatar de be_tnt
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    312
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2005
    Messages : 312
    Points : 84
    Points
    84
    Par défaut
    si je veux ré-utiliser un pointeur, est-ce que je dois faire quelque chose?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    char *value;
     
    value = getenv(VAR1);
     
    [....]
     
    value = getenv(VAR2);

  17. #17
    Expert éminent sénior

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Points : 11 877
    Points
    11 877
    Par défaut
    Citation Envoyé par be_tnt
    si je veux ré-utiliser un pointeur, est-ce que je dois faire quelque chose?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    char *value;
     
    value = getenv(VAR1);
     
    [....]
     
    value = getenv(VAR2);

    Non, c'est très bien comme ça,
    Jc

  18. #18
    Membre régulier Avatar de be_tnt
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    312
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2005
    Messages : 312
    Points : 84
    Points
    84
    Par défaut

Discussions similaires

  1. [Batch] erreur avec la commande CALL
    Par LOBO1986 dans le forum Scripts/Batch
    Réponses: 5
    Dernier message: 26/05/2011, 21h02
  2. [LDAP] Erreur avec la commande smbldap-populate
    Par zyriuse dans le forum Réseau
    Réponses: 5
    Dernier message: 18/10/2010, 20h47
  3. Erreur avec la commande "Type"
    Par Dereck07 dans le forum Macros et VBA Excel
    Réponses: 3
    Dernier message: 10/09/2009, 00h14
  4. Erreur avec la commande copy
    Par Bba_M dans le forum Scripts/Batch
    Réponses: 7
    Dernier message: 14/01/2008, 16h25

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