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 :

Comportement d'allocation mémoire


Sujet :

C

  1. #1
    Membre habitué
    Inscrit en
    Mai 2008
    Messages
    12
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 12
    Par défaut Comportement d'allocation mémoire
    Bonjour à tous


    Mon code est fonctionnel. Mais je cherche à expliquer son comportement
    Voici le 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
    char*p="test ok1 ok2";
    char*ch1,ch,lex;
    char*tab[3];
    ch1=malloc((strlen(p)+1)*sizeof(char)));
    strcpy(ch1,s);
    while (*ch1 && (lex=strpbrk(ch1," "))){
     
             ch=(char*)malloc(((lex-tmp)+1)*sizeof(char));/* mon problème est là*/
            strncpy(ch,ch1,(lex-ch1))[tok-ch1+1]='\0';			
             tab[i++]=ch;        
             ch1=lex+1;
             tab[i]='\0';
     
    }
    ------------------------------
    Le but est de découper slon des espaces et pointer tab[i] sur "le token"
    Quand j'affiche tab[i] j'ai le résulatat attendu ( tab[0]=test et tab[1]=ok1).
    Ma question:
    Normalement quand je passe à la deuxième itération , je m'attends à ce que
    le contenu de "ch" qui contient déja le token "test" soit écrasé. Donc l'affichage doit être seulement : tab[0]=ok1. Mais l'affichage est:
    tab[0]=test
    tab[1]=ok1
    Ch n'est pas ecrasé? c'est bizarre?

    Merci d'avance

  2. #2
    Expert confirmé

    Inscrit en
    Août 2006
    Messages
    3 962
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 3 962
    Par défaut
    Gia,
    Citation Envoyé par yanyin Voir le message
    Bonjour à tous


    Mon code est fonctionnel. Mais je cherche à expliquer son comportement
    Voici le 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
    char*p="test ok1 ok2";
    char*ch1,ch,lex;
    char*tab[3];
    ch1=malloc((strlen(p)+1)*sizeof(char)));
    strcpy(ch1,s);
    while (*ch1 && (lex=strpbrk(ch1," "))){
     
             ch=(char*)malloc(((lex-tmp)+1)*sizeof(char));/* mon problème est là*/
            strncpy(ch,ch1,(lex-ch1))[tok-ch1+1]='\0';			
             tab[i++]=ch;        
             ch1=lex+1;
             tab[i]='\0';
     
    }
    ------------------------------
    Le but est de découper slon des espaces et pointer tab[i] sur "le token"
    Quand j'affiche tab[i] j'ai le résulatat attendu ( tab[0]=test et tab[1]=ok1).
    Ma question:
    Normalement quand je passe à la deuxième itération , je m'attends à ce que
    le contenu de "ch" qui contient déja le token "test" soit écrasé. Donc l'affichage doit être seulement : tab[0]=ok1. Mais l'affichage est:
    tab[0]=test
    tab[1]=ok1
    Ch n'est pas ecrasé? c'est bizarre?

    Merci d'avance
    C'est surtout bien faux :

    ch et lex sont de simples caractères, et tu les utilises comme des pointeurs.

  3. #3
    Membre éclairé
    Homme Profil pro
    Inscrit en
    Octobre 2007
    Messages
    487
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2007
    Messages : 487
    Par défaut
    Tu n’as pas fait une allocation ici
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    while (*ch1 && (lex=strpbrk(ch1," ")))
    Peux tu nous expliquer ce qu’elle fait cette boucle ?

  4. #4
    Membre habitué
    Inscrit en
    Mai 2008
    Messages
    12
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 12
    Par défaut
    Citation Envoyé par droggo Voir le message
    Gia,

    C'est surtout bien faux :

    ch et lex sont de simples caractères, et tu les utilises comme des pointeurs.
    Vous pouvez me donner plus de détails

    merci

  5. #5
    Membre habitué
    Inscrit en
    Mai 2008
    Messages
    12
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 12
    Par défaut
    Citation Envoyé par dot-_-net Voir le message
    Tu n’as pas fait une allocation ici
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    while (*ch1 && (lex=strpbrk(ch1," ")))
    Peux tu nous expliquer ce qu’elle fait cette boucle ?
    Pour l'allocation : une petite erreur à glisser . Strcpy(ch1,p) et non strcpy(ch1,s)
    Pour le while:
    Tanque ce n'est pas '\0' et il y'a une occurence (le retour de strpbrk !=NULL) :
    1- allouer espace mémoire suffisant (pouvant contenir le mot avant *lex)
    2-copier ce mot et ajouter '\0'
    3- affectation
    4-déplacer le pointeur
    5- reprendre de nouveau si c'est vrai

  6. #6
    Expert confirmé

    Avatar de snake264
    Homme Profil pro
    Datascientist chez Leboncoin
    Inscrit en
    Novembre 2006
    Messages
    2 914
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Datascientist chez Leboncoin
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Novembre 2006
    Messages : 2 914
    Par défaut
    Si tu veux définir les variables lex et ch en tant que pointeur il faut que tu mette "*" devant.

  7. #7
    Membre habitué
    Inscrit en
    Mai 2008
    Messages
    12
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 12
    Par défaut
    Citation Envoyé par snake264 Voir le message
    Si tu veux définir les variables lex et ch en tant que pointeur il faut que tu mette "*" devant.
    Oui t'as raison .Mais dans mon vrai code sont des pointeurs.

    je précise encore que ce bout de code est fonctionnel. Il m'affiche ce que je veux voir. Ma question c'est pourqoui le contenue de ch1 n'est pas écrasé? une fois que je passe à la 2ième itération?

  8. #8
    Expert confirmé

    Avatar de snake264
    Homme Profil pro
    Datascientist chez Leboncoin
    Inscrit en
    Novembre 2006
    Messages
    2 914
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Datascientist chez Leboncoin
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Novembre 2006
    Messages : 2 914
    Par défaut
    Comment peuvent-ils être considéré comme des pointeurs alors que tu les déclare comme simple variable ?
    Poste nous ton code complet au moins compilable qu'on puisse voir ce que tu cherche à faire

  9. #9
    Membre habitué
    Inscrit en
    Mai 2008
    Messages
    12
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 12
    Par défaut
    Mon 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
     #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
     
    int main(){
    int i=0;
    char*p="test ok1 ok2";
    char*ch1,*ch,*lex;
    char*tab[3];
    ch1=malloc((strlen(p)+1)*sizeof(char));
    strcpy(ch1,p);
    while (*ch1 && (lex=strpbrk(ch1," "))){
             ch=(char*)malloc(((lex-ch1)+1)*sizeof(char));/* mon problème est là*/
    			   strncpy(ch,ch1,(lex-ch1))[lex-ch1+1]='\0';			
             tab[i++]=ch;        
             ch1=lex+1;
             tab[i]='\0';
    }
    i=0;
    while(tab[i]){
    fprintf(stdout,"tab[%d]= %s\n",i,tab[i]);
    i++;
    }
    return 0;
    }
    Attendez vous à un affichage comme ça :
    tab[0]=test
    tab[1]=ok1

    Merci

  10. #10
    Membre habitué
    Inscrit en
    Mai 2008
    Messages
    12
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 12
    Par défaut
    Et dans ce fichier , je pose ma question avec 2 shéma
    Merci
    Images attachées Images attachées

  11. #11
    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 yanyin Voir le message
    Oui t'as raison .Mais dans mon vrai code sont des pointeurs.

    je précise encore que ce bout de code est fonctionnel. Il m'affiche ce que je veux voir. Ma question c'est pourqoui le contenue de ch1 n'est pas écrasé? une fois que je passe à la 2ième itération?
    Ce code est faux (manque le dernier champ) et inutilement complexe. Ceci fonctionne :
    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
     
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
     
    int main (void)
    {
       /* non modifiable */
       char const *s = "test ok1 ok2";
     
       /* prévoir un pointeur de plus pour le NULL de fin */
       char *tab[4];
     
       /* faire une copie modifiable de la chaine (utilise malloc() */
       char *sdup = strdup (s);     /* POSIX.1 */
     
    /* Parcourir la chaine en remplaçant le séparateur par un 0,
       noter l'adresse de la chaine dans le tableau. */
       char *p = sdup;
       if (sdup != NULL)
       {
          {
             int i = 0;
             tab[i] = p;
             i++;
     
             while ((p = strchr (p, ' ')) != NULL)
             {
                *p = 0;
                p++;
                tab[i] = p;
                i++;
             }
             tab[i] = NULL;
          }
     
    /* afficher */
          {
             int i = 0;
     
             while (tab[i])
             {
                fprintf (stdout, "tab[%d]= %s\n", i, tab[i]);
                i++;
             }
          }
     
          /* libérer */
          free (sdup), sdup = NULL;
       }
       /* supprimer les alias */
       {
          int i = 0;
     
          while (tab[i])
          {
             tab[i] = NULL;
             i++;
          }
       }
     
       return 0;
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    tab[0]= test
    tab[1]= ok1
    tab[2]= ok2
     
    Press ENTER to continue.

  12. #12
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    Ma question c'est pourqoui le contenue de ch1 n'est pas écrasé? une fois que je passe à la 2ième itération?
    Après avoir alloué de la mémoire par le malloc, copié "test" dans cette zone et rangé son adresse dans tab[0], le contenu de ch1 change pour pointer sur la suite de la chaîne "test ok1 ok2".
    La deuxième itération par de la nouvelle position dans la chaîne (correspondant au caractère o de ok1). Le malloc alloue une nouvelle zone mémoire dans laquelle tu places la chaîne "ok1" et sauvegarde l'adresse de cette zone dans tab[1]. Puis la valeur de ch1 change pour pointer sur le o de "ok2".

    Il est normal que tab[0] pointe sur "test" et tab[1] sur "ok1".

  13. #13
    Expert confirmé

    Inscrit en
    Août 2006
    Messages
    3 962
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 3 962
    Par défaut
    Hia,
    Citation Envoyé par yanyin Voir le message
    Oui t'as raison .Mais dans mon vrai code sont des pointeurs.
    Tu sais ce qu'est copier/coller ?

  14. #14
    Membre habitué
    Inscrit en
    Mai 2008
    Messages
    12
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 12
    Par défaut
    Ce n'est que ma première participation . Je m'excuse pour les erreurs qui ont glissé


    Mr Delahaye ,Votre code donne des warning à la compilation
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    gcc -Wall -pedantic -posix -o n.o n.c
    n.c: In function ‘main’:
    n.c:14: attention : implicit declaration of function ‘strdup’
    n.c:14: attention : incompatible implicit declaration of built-in function ‘strdup’
    Il fait un bon découpage et beaucoup plus simple que le mien. Mais je ne veux pas afficher la chaine "OK2" et encore plus je cherche uniquement à comprendre pourqoui le contenue de ch(et pas ch1) n'est pas ecrasé.

    Diogene: si on raisonne sur ch1,c'est vrai .Son contenue ne doit pas bouger
    Par contre ch doit changer à la 2ième itération. En effet tab pointe sur ch et ne sait rien sur ch1. Et si nous tournons ce programme à la main nous devrions avoir(à mon avis) tab[0]=oK1 et tab[1]=ok1puisque tab pointe sur ch et pas sur ch1
    Mon shéma ci haut lui manque un autre pointeur (tab[1]) qui devra pointer encore une fois sur ch.

  15. #15
    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 yanyin Voir le message
    Mr Delahaye ,Votre code donne des warning à la compilation
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    gcc -Wall -pedantic -posix -o n.o n.c
    n.c: In function ‘main’:
    n.c:14: attention : implicit declaration of function ‘strdup’
    n.c:14: attention : incompatible implicit declaration of built-in function ‘strdup’
    Retire -pedantic, il inhibe la déclaration de strdup().

    (et 'Emmanuel', suffira...)

  16. #16
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    nous devrions avoir(à mon avis) tab[0]=oK1 et tab[1]=ok1puisque tab pointe sur ch et pas sur ch1
    Non, parce que lors du deuxième
    ch = malloc(....),
    une nouvelle adresse d'un nouveau bloc de mémoire a été placée dans ch et qu'une nouvelle chaîne
    a été copiée dans ce nouveau bloc.
    strncpy(ch,.....
    tab ne pointe pas sur ch. Le tableau tab contient les adresses successives obtenues par les malloc

  17. #17
    Membre habitué
    Inscrit en
    Mai 2008
    Messages
    12
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 12
    Par défaut
    Citation Envoyé par diogene Voir le message
    tab ne pointe pas sur ch. Le tableau tab contient les adresses successives obtenues par les malloc
    Donc si je libère la mémoire (free(ch)) le contenue de tab ne devra pas bouger puisque l'adresse est déja mémorisee dans tab[i] correspondant et ne sera effacé que par une affectation (tab[i]=NULL) .N'est pas?

    Pour tester ,j'ai ajouté (free(ch)) à la fin de la boucle while et j'ai eu:
    tab[0]=
    tab[1]=

  18. #18
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    Donc si je libère la mémoire (free(ch)) le contenue de tab ne devra pas bouger
    Non.
    Par contre, les adresses contenues dans tab sont des adresses de zones mémoires devenues invalides (libérées par free) et tab contient alors l'adresse de zones détruites. Si on essaie d'afficher les chaînes dont l'adresse est alors dans tab, on va à la catastrophe puisque ces chaînes sont détruites.
    Comment savoir si les adresses placées dans tab sont des adresses mémoires invalides ? Placer le contenu de tab à NULL permet de signifier que ces adresses ne sont pas des adresses d'objets.

  19. #19
    Membre habitué
    Inscrit en
    Mai 2008
    Messages
    12
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 12
    Par défaut
    Merci diogene.
    Tes réponses m'ont convaicu.

  20. #20
    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 yanyin Voir le message
    Merci diogene.
    Tes réponses m'ont convaicu.
    Le problème n'est pas d'être convaincu. Il ne s'agit pas ici d'opinion. La question est "est-ce que tu as compris ?" .

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Pb d'allocation mémoire malloc
    Par oz80 dans le forum C++
    Réponses: 5
    Dernier message: 18/11/2005, 17h23
  2. Limite Allocation Mémoire d'un tableau d'entier
    Par l9ft b9hind dans le forum C++
    Réponses: 5
    Dernier message: 27/10/2005, 19h29
  3. Allocation mémoire
    Par DestyNov@ dans le forum C++
    Réponses: 9
    Dernier message: 23/08/2005, 08h09
  4. [Pointeur] Allocation mémoire
    Par Rayek dans le forum Langage
    Réponses: 22
    Dernier message: 20/05/2005, 10h26
  5. Allocation mémoire dynamique
    Par ITISAR dans le forum VB 6 et antérieur
    Réponses: 6
    Dernier message: 21/01/2005, 09h59

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