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 :

malloc : je ne comprends pas


Sujet :

C

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Août 2006
    Messages
    99
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 99
    Points : 31
    Points
    31
    Par défaut malloc : je ne comprends pas
    Bonjour,

    D'après ce que j'ai compris de ce que j'ai lu dans un tuto,

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    float* mabscisse = NULL; 
    mabscisse = malloc(100 * sizeof(float));
    est équivalent à :

    Or quand j'utilise le premier code ça fait des problèmes...

  2. #2
    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 stokastik
    Bonjour,

    D'après ce que j'ai compris de ce que j'ai lu dans un tuto,

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    float* mabscisse = NULL; 
    mabscisse = malloc(100 * sizeof(float));
    est équivalent à :

    Or quand j'utilise le premier code ça fait des problèmes...
    Il faudrait un code compilable, minimal qui expose le problème car

    ça fait des problèmes...
    est un peu vague...

    Jc

  3. #3
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Points : 12 462
    Points
    12 462
    Par défaut
    Citation Envoyé par stokastik
    Bonjour,

    D'après ce que j'ai compris de ce que j'ai lu dans un tuto,

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    float* mabscisse = NULL; 
    mabscisse = malloc(100 * sizeof(float));
    est équivalent à :

    Certes mais malloc permet une allocation dynamique, il faut donc vérifier le retour de malloc pour savoir si l'allocation s'est bien déroulée. Il suffit d'une erreur ici pour faire foirer ton programme si tu fait pas le test sinon bin expose ton code et les erreurs que tu recois !

    A titre indicatif:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    mabscisse = malloc(100 * sizeof(* mabscisse));
    c'est mieux, surtout pour la maintenance du programme !

  4. #4
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Août 2006
    Messages
    99
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 99
    Points : 31
    Points
    31
    Par défaut
    A titre indicatif:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    mabscisse = malloc(100 * sizeof(* mabscisse));
    c'est mieux, surtout pour la maintenance du programme !
    Ca fait la même chose.


    Il faudrait un code compilable,
    J'essayerai d'isoler un bout de code qui expose le problème.

    Voilà ce que je reçois à la compilation quand je fais ce malloc :
    [Warnig] passing arg1 of 'obtenirSimulation' from incompatible pointeur type
    LA fonction 'obtenirSimulation' étant celle qui reçoit la variable "mabscisse" en premier argument.

  5. #5
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Points : 12 462
    Points
    12 462
    Par défaut
    Citation Envoyé par stokastik
    LA fonction 'obtenirSimulation' étant celle qui reçoit la variable "mabscisse" en premier argument.
    On peut voir sa déclaration et l'appel aussi pour voir le passage des arguments ? Là apparement ce n'est pas un problème d'allocation !

  6. #6
    Membre actif Avatar de Gamdwin
    Inscrit en
    Avril 2005
    Messages
    186
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 186
    Points : 207
    Points
    207
    Par défaut
    Citation Envoyé par stokastik
    Ca fait la même chose.
    Bravo Sherlock.
    Sauf que comme le dit Franck.H, c'est mieux pour la maintenance, puisque si tu changes le type de mabscisse tu n'as rien d'autre à changer.

  7. #7
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 627
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 627
    Points : 30 692
    Points
    30 692
    Par défaut
    Salut,

    Peut etre est ce que je me trompe, mais, visiblement, tu essaie de faire un malloc dans fonction, sur un pointeur que tu as passé en parametre de celle-ci...

    Par exemple
    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
     
    int main(void)
    {
    // déclaration d'un pointeur sur un réel
        float *ptr=NULL;
    //on passe ptr à une procédure  pour la l'allocation
        procedure_alloc(ptr);
    //voire, on récupere le pointeur apres une fonction pour l'allocation
        ptr=fonction_allocation(ptr);
    }
    //l'allocation par procédure
    void procedure_alloc(float *nouveau)
    {
    ptr=malloc(15*sizeof(float));
    }
    //l'allocation par fonction
    float* fonction_alloc(float* nouveau)
    {
       nouveau=malloc(15*sizeof(float));
       return nouveau;
    }
    Hé bien, je peux tout de suite te dire qu'aucune des deux possibilités n'est juste...

    Au pire, cela ne compilera pas, au mieux (enfin, si tant est que ce soit mieux ) ca provoquera des catastrophes à l'utilisation

    En effet, les arguments passés aux routines (procédures et fonctions confondues) sont concidérées comme des variables locales aux routines, et ce, meme si le nom de l'argument est le meme que celui de la variable à transmettre.

    Si l'on veut qu'une routine A puisse passer la variable MaVar à la routine B en argument et récupérer apres la valeur de MaVar déterminée dans la routine B, il faut passer un pointeur sur MaVar à la routine B (ou, s'il s'agit d'une fonction, que B renvoie la nouvelle valeur de l'argument)

    Donc, si tu veux qu'une fonction modifie pour le compte de la fonction appelante la valeur d'un float fournis en argument et renvoie une valeur de réussite/échec, tu devra founrir un pointeur sur ton float, et, si tu veux travailler sur un pointeur de type float, dans les memes conditions tu devras fournir un pointeur de pointeur à ta fonction

    Un petit exemple pour t'en convaincre:
    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
     
    //inclusion des fichiers nécessaires
    #include <stdio.h>
    //prototype des fonctions
    void ChangeNL(int i);
    void ChangePtr(int *i);
    void main(void)
    {
        //un entier que l'on définit à 10
        int entier=10;
        //la preuve est dan l'affichage
        printf("%d\n",entier);
        //Comme tu t'en doute, ChangeNL ne le modifie pas... la preuve
        ChangeNL(entier);
        printf("%d\n",entier);
        //par contre, ChangePtr, elle, le modifie... la preuve
        ChangePtr(&entier);
        printf("%d\n,entier);
    }
    //la fonction ChangeNL
    void ChangeNL(int i)
    {
        printf("on est dans ChangeNL\n");
        i=25;
    }
    //la fonction ChangePtr
    void ChangeNL(int *i)
    {
        printf("on est dans ChangePtr\n");
        //comme i est un pointeur, il faut travailler sur "l'élément visé par i"
        *i=25;
    }
    Evidemment, si dans main, j'avais travaillé avec un pointeur, j'aurais du prévoir le passage d'un pointeur de pointeur pour ChangePtr et que la modification soit prise en compte dans main mais le principe aurait été exactement le meme

    L'utilisation de malloc pour l'allocation d'un pointeur alors que l'on a un pointeur de pointeur se fait alors sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    //il faut faire un malloc sur ce qui est pointé par le pointeur de pointeur
    *PPtr_Argument=malloc(15*sizeof(float));

  8. #8
    Rédacteur

    Avatar de millie
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    7 015
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 7 015
    Points : 9 818
    Points
    9 818
    Par défaut
    C'est également conseillé de forcer la valeur de retour de malloc pour ne pas avoir de problème avec la manipulation du pointeur à coup de ++.

  9. #9
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 379
    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 379
    Points : 41 573
    Points
    41 573
    Par défaut
    koala01 : Tu inverses "au pire" et "au mieux" et tu auras tout bon.

    millie : Tout faux. Il est considéré de ne PAS mettre ce cast inutile, car il peut cacher un oubli d'inclusion de <stdlib.h>.
    Et en C++, on n'utilise pas malloc().

  10. #10
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 627
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 627
    Points : 30 692
    Points
    30 692
    Par défaut
    Citation Envoyé par Médinoc
    koala01 : Tu inverses "au pire" et "au mieux" et tu auras tout bon.
    Disons que... tout dépend du point de vue...
    Du point de vue du débuttant:
    "M** ca ne compile pas ou Youpee, ca compile"
    du point de vue de l'utilisateur
    "M** j'ai une application qui a un comportement aléatoire"

    Finalement, c'est un peu choux vert et vert choux, non? Le résultat étant toujours pareil: un code incorrect et inutilisable...

    Et puis, j'ai bien mis entre parenthese "enfin, si tant est que ce soit un mieux"

  11. #11
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 627
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 627
    Points : 30 692
    Points
    30 692
    Par défaut Tant qu'à faire...
    Tant qu'à faire, voici un code pour une procédure et une fonction qui fonctionneront pour l'allocation dynamique à l'intérieur de celles-ci
    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
     
    #include <stdio.h>
    #include <malloc.h>
    //prototypes des routine
    void ProcAlloc(float **ptr);
    float* FoncAlloc(void);
    int main(void)
    {
        float *pointeur=NULL;
    //allocation par procédure
        ProcAlloc(&pointeur);
    //Il faut vérifier ici que l'allocation aie réussi (pointeur ne vaut plus NULL)
    //pour éviter les pertes de mémoires, si c'est le cas, on libère le pointeur 
    //alloué par la procedure
        if(pointeur!=NULL)
        {
            printf("...ok\n");
            free(pointeur);
        }
        else
        {
            printf("...echoue\n");
        }
        //on tente avec la fonction
        pointeur=FoncAlloc();
        //on libère le pointeur avant de quitter
        free(pointeur);
        return EXIT_SUCCESS;
    }
    void ProcAlloc(float **ptr)
    {
        printf("allocation dans la procedure");
        *ptr=malloc(15*sizeof(float));
    }
    float* FoncAlloc()
    {
    //comme il n'y a pas d'argument, il faut déclarer un pointeur de travail
    //L'astuce est que si la référence à ce pointeur sera détruite en sortie de fonction
    //l'allocation dynamique restera
        float *ptr;
        printf("allocation dans la fonction");
        ptr=malloc(15*sizeof(float))
        if(ptr!=NULL)
        {
            printf("...ok");
        }
        else
        {
            printf("...echoué");
        }
        return ptr;
    }

  12. #12
    Rédacteur

    Avatar de millie
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    7 015
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 7 015
    Points : 9 818
    Points
    9 818
    Par défaut
    Citation Envoyé par Médinoc
    millie : Tout faux. Il est considéré de ne PAS mettre ce cast inutile, car il peut cacher un oubli d'inclusion de <stdlib.h>.
    Et en C++, on n'utilise pas malloc().

    Je n'ai jamais parlé de C++ !!!!

  13. #13
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 379
    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 379
    Points : 41 573
    Points
    41 573
    Par défaut
    Pardon, j'avais vu un C imaginaire.
    Mais dans ce cas, je ne vois pas trop ce que ton post voulait dire...

  14. #14
    Rédacteur

    Avatar de millie
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    7 015
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 7 015
    Points : 9 818
    Points
    9 818
    Par défaut
    Il me semblait (arrêtez moi si je me trompe) mais mes profs m'ont toujours dis ça :

    par exemple dans le code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    int i;
    double *d;
    double c;
     
     d = malloc(10  *sizeof(double));
     for(i=0; i<5;i++)
     {
       c= *d;
       d++;
     }
    Le code n'a pas d'interêt mais c'est pour faire une exemple. Enfin bref, pour moi, le faire de pas faire de cast au retour de malloc fait qu'il y a un mauvais alignement mémoire au niveau des double. Lors du d++, on ne saute que d'un sizeof(void*) car malloc retourne normalement un void*.

    Alors qu'en réalisant le cast, le saut est un bon saut.

  15. #15
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 379
    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 379
    Points : 41 573
    Points
    41 573
    Par défaut
    ben non, d est un double *, cast au retour de malloc() ou non.

    Et si d était un void*, je crois bien que d++ ne compilerait pas.

  16. #16
    Membre actif Avatar de Gamdwin
    Inscrit en
    Avril 2005
    Messages
    186
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 186
    Points : 207
    Points
    207
    Par défaut
    Citation Envoyé par millie
    Il me semblait (arrêtez moi si je me trompe) mais mes profs m'ont toujours dis ça :
    [...]
    Lors du d++, on ne saute que d'un sizeof(void*) car malloc retourne normalement un void*.

    Alors qu'en réalisant le cast, le saut est un bon saut.
    Change de profs.

  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 Médinoc
    ben non, d est un double *, cast au retour de malloc() ou non.

    Et si d était un void*, je crois bien que d++ ne compilerait pas.
    En effet, la norme refuse l'arithmétique sur le void* mais les extensions GNU font que gcc l'accepte...

    Warning qui permet de le voir :

    -Wpointer-arith

    [EDIT]
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    int main()
    {
        int i;
        void *a=&i;
     
        a++;
        return 0;
    }
    $> gcc testvoid.c -Wpointer-arith
    testvoid.c: In function 'main':
    testvoid.c:6: warning: wrong type argument to increment
    [/EDIT]

    Jc

  18. #18
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Août 2006
    Messages
    99
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 99
    Points : 31
    Points
    31
    Par défaut
    On peut voir sa déclaration et l'appel aussi pour voir le passage des arguments ?
    Pour voir la fonction 'obtenirSimulation', mon prog est dans ce topic : http://www.developpez.net/forums/sho...d.php?t=199625

  19. #19
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Août 2006
    Messages
    99
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 99
    Points : 31
    Points
    31
    Par défaut
    koala01, ce que je retire de ce que tu dis est que je dois taper :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
      float* preabscisse=NULL;
     
      *preabscisse=malloc(TAILLE * sizeof(float));
    mais cela n'est pas accepté à la compilation. J'ai essayé :


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
      float** preabscisse=NULL;
     
      *preabscisse=malloc(TAILLE * sizeof(float));
    qui me semble plus cohérent, mais alors le type de 'preabscisse' n'est plus acceptée par ma fonction.

  20. #20
    Membre actif Avatar de Gamdwin
    Inscrit en
    Avril 2005
    Messages
    186
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 186
    Points : 207
    Points
    207
    Par défaut
    Citation Envoyé par stokastik
    koala01, ce que je retire de ce que tu dis est que je dois taper :
    Lit une nouvelle fois le post de koala1. Et essaie de comprendre le mécanisme des pointeurs avant de mettre des astérisques au hasard.

    (lien didactique et amusant : http://cslibrary.stanford.edu/104 )

Discussions similaires

  1. Erreur Objet requis : 'this' --> Comprend pas!!
    Par Grozeil dans le forum ASP
    Réponses: 3
    Dernier message: 30/03/2005, 09h46
  2. [thread][methodologie]Quelque chose que je ne comprends pas!
    Par norkius dans le forum Général Java
    Réponses: 5
    Dernier message: 16/03/2005, 14h01
  3. sql ne comprend pas mon where!et me demande des parametres
    Par marie10 dans le forum Langage SQL
    Réponses: 10
    Dernier message: 20/04/2004, 11h08
  4. [Rave] un message que je ne comprends pas
    Par Clotilde dans le forum Rave
    Réponses: 2
    Dernier message: 30/09/2003, 21h46

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