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 :

Libération de l'espace dynamique alloué


Sujet :

C

  1. #1
    Débutant
    Inscrit en
    Mai 2009
    Messages
    392
    Détails du profil
    Informations forums :
    Inscription : Mai 2009
    Messages : 392
    Points : 35
    Points
    35
    Par défaut Libération de l'espace dynamique alloué
    Bonsoir,
    J'ai un fichier contient deux champs: objet et attribut nommé "exemple.txt" :

    2 11
    4 11
    10 10
    5 O1
    .....
    .....

    Sachant que on a la même taille pour tous les attributs de tous les objets dans notre exemple on a la taille = 2.
    Cette taille peut changer d'un exemple à l'autre donc on ne connait pas la taille d'attribut en avance.

    Je voudrais calculer la taille de l'attribut puis vérifier si on dans ce fichier si on a au moins un objet qui possède un attribut tout à 1 c'est à dire la chaine "11" dans notre cas.
    la fonction verifier() nous retourne 1 si il existe la chaine "11" sinon O.

    Voici mon essai :


    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
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    int verifier(int taille)
    {
    FILE *fp;
    char *chaine,s[100],attribut[32];
    int i,trouve=0,objet=0;
    chaine = (char *) malloc(taille);
    for(i=0; i < taille; i++)
    chaine[i]='1';
    chaine[taille]='\0';
    printf("chaine=%s\n",chaine);
    pFTrie = fopen("exemple.txt","r");
    while (fgets(s, 100, fp))
    {
    sscanf(s,"%d%s",objet,attribut);
    if(memcmp(attribut,chaine,taille))
    {
    free(chaine);
    fclose(fp);
    return 1;
    }
    }
    free(chaine);
    fclose(fp);
    return 0;
    }
     
    int main()
    {
    FILE *fp;
    int trouve=0,taille;
    fp=fopen("exemple.txt");
    While (fgets(s,100,fp))
    sscanf(s,"%d%s",&objet,attribut);
    taille=strlen(attribut);
    trouve = verifier(taille);
    printf("valeur de retour %d\n",trouve);
     
    return 0;
    }

    Mais, le message suivant n'affiche pas:
    printf("valeur de retour %d\n",trouve);

    -Pourquoi ?

    lorsque je lance l'exécution après la compilation j'ai le message suivant:
    HEAP CORRUPTION DETECTED : after normal (#95) at 0*01020068.
    CRT detected that the application wrote to memory after end of heap buffer.



    Ceci à cause d 'instruction free chaine(); dans la fonction verifier () car je supprime cette instruction donc l'exection se passe.
    Mais, comment on va liberer l'espace dynamique louée par chaine[taille] ?
    - l'allocation et la libération de l'espace dynamique char *chaine est bien définie ?
    - Existe-t-il le type boolean comme un type des données ? comment le déclare ?
    - On peut utiliser le type boolean comme valeur de retour pour la fonction verifier() ?

  2. #2
    Membre confirmé
    Inscrit en
    Juillet 2005
    Messages
    512
    Détails du profil
    Informations forums :
    Inscription : Juillet 2005
    Messages : 512
    Points : 641
    Points
    641
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    chaine[taille]='\0';
    Ici tu écrit en dehors de ton tableau !
    le dernier élément du tableau à pour indice taille-1

  3. #3
    Débutant
    Inscrit en
    Mai 2009
    Messages
    392
    Détails du profil
    Informations forums :
    Inscription : Mai 2009
    Messages : 392
    Points : 35
    Points
    35
    Par défaut
    Bonjour,

    Voici le programme :
    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
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    int verifier(int taille)
    {
    FILE *fp;
    char *chaine,s[100],attribut[32];
    int i,trouve=0,objet=0;
    chaine = (char *) malloc(taille);
    for(i=0; i < taille; i++)
    chaine[i]='1';
    chaine[taille]='\0';
    printf("chaine=%s\n",chaine);
    fp = fopen("exemple.txt","r");
    while (fgets(s, 100, fp))
    {
    sscanf(s,"%d%s",objet,attribut);
    if(memcmp(attribut,chaine,taille))
    {
    free(chaine);
    fclose(fp);
    return 1;
    }
    }
    free(chaine);
    fclose(fp);
    return 0;
    }
     
    int main()
    {
    FILE *fp;
    char s[100],attribut[32];
    int trouve=0,taille,objet;
    fp=fopen("exemple.txt","r");
    while (fgets(s,100,fp)!= NULL)
    sscanf(s,"%d%s",&objet,attribut);
    taille=strlen(attribut);
    trouve = verifier(taille);
    printf("valeur de retour %d\n",trouve);
     
    return 0;
    }
    Non. on a taille= 2
    Chaine[0]='1' et Chaine[1]='1'
    et il faut ajouter '\0' à la fin de la chaine donc Chaine[taille]='\0'
    Que pensez-vous ?

  4. #4
    Membre chevronné
    Profil pro
    Inscrit en
    Août 2006
    Messages
    1 104
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 1 104
    Points : 1 750
    Points
    1 750
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    taille=strlen(attribut);
    trouve = verifier(taille);
    La fonction strlen() calcule la longueur de la chaîne de caractères s, sans compter le caractère nul `\0' final.
    Dans la fonction "verifier" :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    chaine = (char *) malloc(taille+1);

  5. #5
    Membre confirmé
    Inscrit en
    Juillet 2005
    Messages
    512
    Détails du profil
    Informations forums :
    Inscription : Juillet 2005
    Messages : 512
    Points : 641
    Points
    641
    Par défaut
    Non. on a taille= 2
    Chaine[0]='1' et Chaine[1]='1'
    et il faut ajouter '\0' à la fin de la chaine donc Chaine[taille]='\0'
    Que pensez-vous ?
    ça fait 3 caractères à écrire les deux '1' et le '\0'
    il te faut donc un tableau de taille 3
    Les indices des tableaux vont toujours de 0 à Taille-1

  6. #6
    Débutant
    Inscrit en
    Mai 2009
    Messages
    392
    Détails du profil
    Informations forums :
    Inscription : Mai 2009
    Messages : 392
    Points : 35
    Points
    35
    Par défaut
    Merci. Ca marche.
    taille +1 ou lieu de taille.

    Une seule question:
    - quelle est la différence entre :
    chaine = (char *) malloc((taille+1));
    chaine = (char *) malloc((taille+1)*sizeof(char));

    Les deux marchent.

  7. #7
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    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 369
    Points : 41 519
    Points
    41 519
    Par défaut
    sizeof(char) vaut 1 par définition.

    Mais ça devient plus compliqué/intéressant quand on touche aux caractères larges (pour Unicode): sizeof(wchar_t) vaut souvent 2 ou 4, et sous Windows, sizeof(TCHAR) peut valoir 1 ou 2 selon les options, donc il devient important de les préciser.
    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.

  8. #8
    Membre averti
    Homme Profil pro
    DevOps AWS
    Inscrit en
    Juillet 2009
    Messages
    120
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : DevOps AWS
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2009
    Messages : 120
    Points : 334
    Points
    334
    Par défaut
    Une seule question:
    - quelle est la différence entre :
    chaine = (char *) malloc((taille+1));
    chaine = (char *) malloc((taille+1)*sizeof(char));

    Les deux marchent.
    Selon ton systeme d'exploitation ton char sera sur 1octet ou plus de mémoire c'est différent entre unix et windows !
    le sizeof est important pour la compatibilité avec d'autre systeme !
    de même on préfèrera un sizeof(*chaine) a sizeof(char) pour la simple et bonne raison que le jour ou ta chaine de char* devient une chaine d'int* tu devra relire tout ton code pour changer tes malloc a cause du sizeof(char)

    Je te conseillerai de te faire une fonction xmalloc qui vérifie la valeur de retour de ta fonction malloc et qui renvoi un pointer void*

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    void     *xmalloc(void *str, int size)
    {
    void    *string;
     
    if ((string = malloc((size + 1) *sizeof(*str))) == NULL)
    puts("Can't allocate Memory\n");
    string[size] = '\0';
    return (string);
    }
    de mémoire le compilo va râler a cause du pointer void* que tu lui passes.
    C'est la meilleur solution que j'ai trouve pour ne pas oublier de vérifier mes valeurs de retour de fonctions systeme.

    Tu peux aussi utiliser errno (RTFM hein ^^) pour avoir un message plus précis.

  9. #9
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 689
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par LordMacharius Voir le message
    Je te conseillerai de te faire une fonction xmalloc qui vérifie la valeur de retour de ta fonction malloc et qui renvoi un pointer void*

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    void     *xmalloc(void *str, int size)
    {
    void    *string;
     
    if ((string = malloc((size + 1) *sizeof(*str))) == NULL)
    puts("Can't allocate Memory\n");
    string[size] = '\0';
    return (string);
    }
    sizeof(*str) => Sachant que "*str" est de type "void" je suis étonné que ta fonction fonctionne correctement !!! D'ailleurs quand un compilo râle, c'est qu'il y a une raison donc une bonne approche est de s'arranger pour qu'il ne râle plus.
    Visiblement cette fonction étant destinée à allouer une chaine, autant rester en char !!!
    Toutefois, la plus-value de cette fonction (par rapport à calloc qui initialise la zone allouée à 0) étant seulement de t'afficher un message sur la sortie standard (et même pas la sortie d'erreur), je doute de sa réelle utilité. Par ailleurs, les connaisseurs apprécieront le remplissage de string[size] même en cas d'allocation échouée (Emmanuel, surtout ne passe pas par là )...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  10. #10
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Points : 4 637
    Points
    4 637
    Par défaut
    Citation Envoyé par LordMacharius Voir le message
    Selon ton systeme d'exploitation ton char sera sur 1octet ou plus de mémoire c'est différent entre unix et windows !
    le sizeof est important pour la compatibilité avec d'autre systeme !
    Par definition sizeof(char) vaut 1 (et ce quel que soit la taille de ton char : 1 octet, 9 bits, 4 octets, etc.), il s'agit de la référence.
    Toutes les autres tailles sont données en fonction de celle-ci

    Citation Envoyé par LordMacharius Voir le message
    de même on préfèrera un sizeof(*chaine) a sizeof(char) pour la simple et bonne raison que le jour ou ta chaine de char* devient une chaine d'int* tu devra relire tout ton code pour changer tes malloc a cause du sizeof(char)
    Tout à fait d'accord sur ce point. A condition que chaine ne soit pas un void*.

    Citation Envoyé par LordMacharius Voir le message
    Je te conseillerai de te faire une fonction xmalloc qui vérifie la valeur de retour de ta fonction malloc et qui renvoi un pointer void*

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    void     *xmalloc(void *str, int size)
    {
    void    *string;
     
    if ((string = malloc((size + 1) *sizeof(*str))) == NULL)
    puts("Can't allocate Memory\n");
    string[size] = '\0';
    return (string);
    }
    de mémoire le compilo va râler a cause du pointer void* que tu lui passes.
    C'est la meilleur solution que j'ai trouve pour ne pas oublier de vérifier mes valeurs de retour de fonctions systeme.

    Tu peux aussi utiliser errno (RTFM hein ^^) pour avoir un message plus précis.
    Fonction fausse et inutile.
    En plus des remarques déjà fournies par Sve@r (sizeof(void), message d'erreur sur la sortie standard dans une fonction couche basse, déréférencement d'un pointeur NULL), je rajouterais que :
    • Je ne vois pas l'intérêt pour une fonction d'allocation mémoire générique d'allouer plus que nécessaire et de rajouter un 0 après la mémoire demandé.
    • Si l'idée était de faire une fonction de gestion de chaîne de caractère, elle porte mal son nom, je ne vois pas l'intérêt d'utiliser des void* et surtout à quoi peut-elle bien servir puisque la chaîne, même correctement terminée, contient n'importe quoi. Si le but est de dupliquer une chaîne, la fonction strdup() (ou un implémentation personnelle de celle-ci lorsqu'elle n'est pas disponible) est plus efficace.

  11. #11
    Membre averti
    Homme Profil pro
    DevOps AWS
    Inscrit en
    Juillet 2009
    Messages
    120
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : DevOps AWS
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2009
    Messages : 120
    Points : 334
    Points
    334
    Par défaut
    Mouarf
    c'est pas la fonction que j'utilise exactement !
    simplement parce que j'utilise d'autre fonction de mon cru !

    Celle qui est chez moi fait un zoli EXIT si je ne peux pas allouer mon pointeur ! et se sert de la sortie d'erreur .

    Des que j'ai l'occasion je montrerai le code dont je me sert !

    Je tiens aussi a préciser que je n'ai eu le droit qu'a malloc , des bêtes write et fonction essentiel pour faire un programme en C . (Je suis encore Étudiant ^^ dans une école ou les fonctions font 25lignes , et ou on recode tout ce dont on a besoin !)

    Le but de cette fonction est juste d'allouer ma chaine et d'être sur d'avoir le caractère de fin !
    gain de temps car je sais que j'ai pas a tester le caractère de fin de chaine ! De plus même si elle est remplie de rien du tout je ne test jamais ce que contient ma chaine je la remplie juste après mon allocation.

  12. #12
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 689
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par LordMacharius Voir le message
    Mouarf
    c'est pas la fonction que j'utilise exactement !
    simplement parce que j'utilise d'autre fonction de mon cru !

    Celle qui est chez moi fait un zoli EXIT si je ne peux pas allouer mon pointeur ! et se sert de la sortie d'erreur .
    exit c'est uniquement à mettre dans le main. Un programme c'est comme des poupées russes. Si on rentre dans une fonction, on ressort par la fonction. Et comme on rentre par le main...

    Citation Envoyé par LordMacharius Voir le message
    Des que j'ai l'occasion je montrerai le code dont je me sert !
    Oui, ça nous intéresse...

    Citation Envoyé par LordMacharius Voir le message
    Le but de cette fonction est juste d'allouer ma chaine et d'être sur d'avoir le caractère de fin !
    calloc()

    Citation Envoyé par LordMacharius Voir le message
    gain de temps car je sais que j'ai pas a tester le caractère de fin de chaine ! De plus même si elle est remplie de rien du tout
    Justement ta zone ne contient pas "rien du tout" (le "rien" n'existe pas pour une variable) mais des octets aléatoires.

    Citation Envoyé par LordMacharius Voir le message
    je ne test jamais ce que contient ma chaine je la remplie juste après mon allocation.
    Et tu la remplis comment ? Via une fonction str (style strcpy()) ? Alors le '\0' est automatiquement positionné par la fonction (à l'exception de strncpy() si le nombre "n" est atteint)
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  13. #13
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Points : 4 637
    Points
    4 637
    Par défaut
    Citation Envoyé par LordMacharius Voir le message
    Celle qui est chez moi fait un zoli EXIT si je ne peux pas allouer mon pointeur ! et se sert de la sortie d'erreur .
    L'utilisation d'un exit() ici résout certes une partie des problèmes remonté mais n'est pas forcément pertinent.
    La sortie pure et simple et brutale d'un programme lorsqu'une telle erreur d'allocation est rencontrée n'est pas toujours une solution envisageable (il peut être nécessaire des logger l'erreur, d'enregistrer l'état en cours ou des modifications effectuées, de relâcher certains ressource, de continuer à fonctionner en mode dégradé, de différer la tentative d'allocation, etc.) et il est très rare qu'une fonction d'une couche aussi basse puisse prendre seule la décision du traitement à effectuer.

    Bref, ce choix peut convenir dans certains cas mais est loin d'être généralisable et la fonction est difficilement réutilisable.


    Citation Envoyé par LordMacharius Voir le message
    Le but de cette fonction est juste d'allouer ma chaine et d'être sur d'avoir le caractère de fin !
    gain de temps car je sais que j'ai pas a tester le caractère de fin de chaine ! De plus même si elle est remplie de rien du tout je ne test jamais ce que contient ma chaine je la remplie juste après mon allocation.
    Dans ce cas, le nom de la fonction et le type des paramètres est mal choisi.

    En outre le fonctionnement n'est pas classique (allocation d'une taille supérieure à la demande) et, dans de nombreux cas, l'initialisation du tableau à sa création ou l'utilisation d'une fonction du type strdup() sera probablement plus pertinent.

Discussions similaires

  1. 1Mo d'espace non alloué en début de DD : pourquoi?
    Par honeydew dans le forum Windows Vista
    Réponses: 1
    Dernier message: 29/08/2008, 23h39
  2. libération de toute la mémoire allouée
    Par salseropom dans le forum C
    Réponses: 17
    Dernier message: 05/11/2007, 16h36
  3. Libération mémoire d'objet dynamique
    Par Romvaillant dans le forum C++
    Réponses: 17
    Dernier message: 13/10/2007, 22h46
  4. Réponses: 8
    Dernier message: 14/12/2006, 23h37
  5. Espace disque alloué pour les entiers
    Par stos dans le forum SQL Procédural
    Réponses: 4
    Dernier message: 30/10/2006, 14h17

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