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 :

Allocation dynamique, malloc, free


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé Avatar de nl.smart
    Homme Profil pro
    ouvrier
    Inscrit en
    Avril 2019
    Messages
    156
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : ouvrier
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2019
    Messages : 156
    Points : 541
    Points
    541
    Par défaut Allocation dynamique, malloc, free
    Bonjour,

    Le code ci-dessous fonctionne mais il affiche un message d'erreur en fin d’exécution dans la console lorsque le nombre de personnes dépasse 2

    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
    #include <stdio.h>  // ok linux
    #include <stdlib.h> //
    #include <time.h>   //
    #include <string.h>
     
    int main()
    {
        int nbre_personnes, i = 0;
     
        char *prenom_personnes[50];
     
        int *ptr_age_personnes = NULL;
     
        printf("\n Combien de personnes sont ici présentes ? ");
        scanf("%d", &nbre_personnes);
     
        if (nbre_personnes > 0)
        {
            *prenom_personnes = malloc(nbre_personnes * sizeof (int)); // il doit y avoir une erreur ici, le pointeur et int...
     
            ptr_age_personnes = malloc(nbre_personnes * sizeof (int));
     
            if (nbre_personnes == 0)
            {
                exit(0);
            }
     
            for (i = 0; i < nbre_personnes ; i++)
            {
                printf("\n Quel est le prénom de la personne %d ? ", i + 1);
                scanf("%s", prenom_personnes[i]);
            }
     
            for (i = 0; i < nbre_personnes ; i++)
            {
                printf("\n Quel âge a %s ? ", prenom_personnes[i]);
                scanf("%d", &ptr_age_personnes[i]);
            }
     
            for (i = 0; i < nbre_personnes ; i++)
            {
                printf("\n %s a %d an%c ", prenom_personnes[i], ptr_age_personnes[i], ptr_age_personnes[i] > 1 ? 's' : ' ');
            }
     
            free(ptr_age_personnes); // Un seul malloc est libéré, un messages d'erreur s'affiche dans l'ide si j'essaye de libérer le second.
     
            printf("\n");
        }
     
        return 0;
    }
    message d'erreur de la console ci-dessous :

    Nom : Allocation dynamique, malloc, free....png
Affichages : 2257
Taille : 12,2 Ko

    Merci pour vos lumières, les corrections et le cour que vous me donnerez :-)

    Nicolas.

  2. #2
    Expert confirmé
    Avatar de gerald3d
    Homme Profil pro
    Conducteur de train
    Inscrit en
    Février 2008
    Messages
    2 293
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Conducteur de train
    Secteur : Transports

    Informations forums :
    Inscription : Février 2008
    Messages : 2 293
    Points : 4 943
    Points
    4 943
    Billets dans le blog
    5
    Par défaut
    Bonsoir.

    prenom_personnes est déclaré comme un tableau de pointeur.

    Ligne 19 tu perds le pointeur sur le premier élément de ce tableau en le remplaçant par une simple allocation.
    Il faut écrire prenom_personnes [x] = malloc (); où x est un index sur les éléments du tableau.

    Autre remarque. La condition ligne 23 ne sert à rien puisqu’elle est incluse dans la condition qui vérifie que nbre_personnes>0.

  3. #3
    Membre régulier
    Homme Profil pro
    Autres
    Inscrit en
    Août 2008
    Messages
    39
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Autres

    Informations forums :
    Inscription : Août 2008
    Messages : 39
    Points : 82
    Points
    82
    Par défaut
    Salut, tu utilises des pointeurs et tu fais des allocations dynamiques, donc je pense que tu en es assez loin pour utiliser des structures qui serait plus adapter pour ton code.
    Ah oui, si tu alloues 50 fois un prenom, alors 50 fois faudra faire un free(). Il y a mieux mais bon je te laisse chercher.
    Et en temps normal, on vérifie les retours de malloc, au cas ou sa renvoie NULL et que tu te retrouves bien embeter


    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
     
    #include <stdio.h>  // ok linux
    #include <stdlib.h> //
    #include <time.h>   //
    #include <string.h>
     
    int main()
    {
        int nbre_personnes, i = 0;
     
        char *prenom_personnes[50]; // Tableau de 50 pointeurs de type char * ( potentiellement 50 prenoms ) 
     
        int *ptr_age_personnes = NULL;
     
        printf("\n Combien de personnes sont ici présentes ? ");
        scanf("%d", &nbre_personnes);
     
        if (nbre_personnes > 0)
        {
            // Ici il y a un probleme, tu ne connais pas encore le nombre de caractere pour "prenom_personnes" pour allouer de la memoire
            // De plus ton allocation est fausse ce serait plutot pour le premier prenom : "prenom_personnes[0]" Tu as 50 pointeurs, donc ici ce sera de 0 à 49 pour l'indice
            // Pour recuperer les prenoms tu devrais utiliser fgets, car scanf faut le maitriser. Prototypes : char * fgets( char * string, int maxLength, FILE * stream );   Ici à la place de stream tu indiques stdin pour ton clavier
            // Tes allocations doivent etre faites au moment ou tu recuperes les prenoms
            // Tu peux aussi utiliser la fonction strnlen pour connaitre le nombre de caractere entrer par l'utilisateur en fixant une limite pour la taille devant etre allouer et prevoir + 1 pour le caractere de fin de chaine
            *prenom_personnes = malloc(nbre_personnes * sizeof (int)); // Ici tu alloues le nombre de personnes multiplier par la taille d'un int, sa ne va pas
     
            ptr_age_personnes = malloc(nbre_personnes * sizeof (int));
     
            if (nbre_personnes == 0)
            {
                exit(0);
            }
     
            for (i = 0; i < nbre_personnes ; i++)
            {
                printf("\n Quel est le prénom de la personne %d ? ", i + 1);
                scanf("%s", prenom_personnes[i]);
            }
     
            for (i = 0; i < nbre_personnes ; i++)
            {
                printf("\n Quel âge a %s ? ", prenom_personnes[i]);
                scanf("%d", &ptr_age_personnes[i]);
            }
     
            for (i = 0; i < nbre_personnes ; i++)
            {
                printf("\n %s a %d an%c ", prenom_personnes[i], ptr_age_personnes[i], ptr_age_personnes[i] > 1 ? 's' : ' ');
            }
     
            free(ptr_age_personnes); // Un seul malloc est libéré, un messages d'erreur s'affiche dans l'ide si j'essaye de libérer le second.
     
            printf("\n");
        }
     
        return 0;
    }

  4. #4
    Membre confirmé Avatar de nl.smart
    Homme Profil pro
    ouvrier
    Inscrit en
    Avril 2019
    Messages
    156
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : ouvrier
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2019
    Messages : 156
    Points : 541
    Points
    541
    Par défaut
    Bonjour,

    Merci pour vos réponses, il y a matière à travailler.

    Les structures seront l'étape suivante pour cet exemple d'allocation dynamique.

    Je me penche sur vos explications et je reviendrai plus tard avec un meilleur code.

    J'ai retravaillé le code ce matin, le voilà, il en reste à corriger...

    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
     
    #include <stdio.h>  // ok linux
    #include <stdlib.h> //
    #include <time.h>   //
    #include <string.h>
     
    int main()
    {
        int nbre_personnes, i = 0;
     
        char *prenom_personnes;
     
        int *ptr_age_personnes;
     
        printf("\n Combien de personnes sont ici présentes ? ");
        scanf("%d", &nbre_personnes);
     
            prenom_personnes = (char *) malloc(50 * sizeof (char));
     
            ptr_age_personnes = (int *) malloc(4 * sizeof(int));
     
            if (prenom_personnes == 0 || ptr_age_personnes == 0)
            {
                exit(0);
            }
     
            for (i = 0; i < nbre_personnes ; i++)
            {
                printf("\n Quel est le prénom de la personne %d ? ", i + 1);
                scanf("%s", &prenom_personnes[i]);
            }
     
            for (i = 0; i < nbre_personnes ; i++) // il y a un problème avec cette boucle lors de l'exécution du code, je verrai ça demain
            {
                printf("\n Quel âge a %s ? ", &prenom_personnes[i]);
                scanf("%d", &ptr_age_personnes[i]);
            }
     
            for (i = 0; i < nbre_personnes ; i++)
            {
                printf("\n %s a %d an%c ", &prenom_personnes[i], ptr_age_personnes[i], ptr_age_personnes[i] > 1 ? 's' : ' ');
            }
     
            free(prenom_personnes);
            free(ptr_age_personnes);
     
            printf("\n");
     
        return 0;
    }
    Nicolas.

  5. #5
    Membre régulier
    Homme Profil pro
    Autres
    Inscrit en
    Août 2008
    Messages
    39
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Autres

    Informations forums :
    Inscription : Août 2008
    Messages : 39
    Points : 82
    Points
    82
    Par défaut
    Inutile de caster le retour de malloc


    EDIT : Je te montre juste un bout de codes fonctionnel, mais qu'on ecrit pas de cette façon, pourquoi ?
    1 : Aucune vérification du retour de malloc()
    2 : fonction de saisie devant être personnaliser, ton programme est à la merci de l'utilisateur
    3 : Si pendant une allocation il y a une erreur, alors boom, fuite mémoire

    Je te laisse rendre ton code plus robuste en étudiant les corrections faites, mais loin d’être parfaite car j'ai garder toute l'organisation de ton programme, et j'ai pas vérifier mes allocations et gérer les cas plus hard

    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 <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    #define MAX_PRENOM 40
     
    int main(void)
    {
        int nbre_personnes;
        int nbr;
        int i = 0;
        char buf[MAX_PRENOM];
        char **prenom_personnes; // Ici création d'un pointeur de type char * qui va pointer sur un pointeur ou des pointeurs de type char *
        int *ptr_age_personnes;
     
        printf("\n Combien de personnes sont ici présentes ? ");
        scanf("%d", &nbre_personnes);
        if (nbre_personnes <= 0)
        {
          printf("\n***Le programme va se terminer, erreur de saisie***\n");
          return EXIT_FAILURE;
        }
     
        prenom_personnes = malloc(nbre_personnes * sizeof (char *)); // Création du tableau de pointeurs de type char *, avec pour un pointeur char * == une chaine à allouer.
        ptr_age_personnes = malloc(nbre_personnes * sizeof(int));
     
        for (i = 0 ; i < nbre_personnes ; i++)
        {
          printf("\n Quel est le prénom de la personne %d ? ", i + 1);
          scanf("%s", buf);
          nbr = strlen(buf); // strlen() retourne le nombre de caractères contenu dans buf sans le caractère de fin de chaine
          printf("Nombre de caracteres du prenom : %d\n", nbr);
          prenom_personnes[i] = malloc((nbr + 1) * sizeof(char));
          memmove(prenom_personnes[i], buf, nbr + 1); // Avant de comprendre ce que fait memmove(), tu peux à la place utiliser strncpy() avec les mêmes arguments
     
          printf("\n Quel âge a %s ? ", prenom_personnes[i]);
          scanf("%d", &ptr_age_personnes[i]);
        }
     
        printf("\n");
        for (i = 0 ; i < nbre_personnes ; i++)
        {
          printf("%s a %d an%c\n", prenom_personnes[i], ptr_age_personnes[i], ptr_age_personnes[i] > 1 ? 's' : ' ');
        }
        printf("\n");
     
        for (i = 0 ; i < nbre_personnes ; i++)
        {
          free(prenom_personnes[i]);
        }
     
        free(prenom_personnes);
        free(ptr_age_personnes);
     
     
        return EXIT_SUCCESS;
    }

  6. #6
    Membre confirmé Avatar de nl.smart
    Homme Profil pro
    ouvrier
    Inscrit en
    Avril 2019
    Messages
    156
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : ouvrier
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2019
    Messages : 156
    Points : 541
    Points
    541
    Par défaut
    Bonjour,

    Comme je le craignais en créant ce poste des notions non vues (mais que je devine pointer à l'horizon) ont été abordées :

    _ buffer
    _ fonction memmove() et strncpy()
    _ saisie de texte sécurisée, liée au buffer (j'ai hâte d'aborder ce point, par ce qu'à l’heure actuelle bonjour les fuites mémoires et autres bugs potentiels dans mon code avec scanf )
    _ pointeur d'adresse sur l'adresse d'une variable (jusqu'à présent un pointeur se limitait pour moi à être une variable qui contenait l'adresse d'une autre variable)
    _ ...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
        /* écrit par gerald3d, citation que j'avais alors copiée et conservée
        char : variable de type entier pouvant aller de -127 à +128
        char* : pointeur d'adresse sur une variable de type char
        char ** : pointeur d'adresse sur l'adresse d'une variable de type char
        */
    ci-dessous le code réalisé ce matin fonctionnant sous linux puis testé sous windows.

    La vérification des malloc est faite au début du programme tout comme leur libération en fin de programme, manque la saisie de texte sécurisée pour laquelle je reviendrai plus tard car non abordée dans le cour que je suis

    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
    #include <stdio.h>  // ok linux et windows
    #include <stdlib.h> //
    #include <time.h>   //
    #include <string.h>
     
    int main()
    {
        int nbre_personnes, i = 0;
     
        char **ptr_prenom_personnes = NULL; // création d'un pointeur d'adresse sur l'adresse d'une variable de type char
     
        int *ptr_age_personnes = NULL;
     
        printf("\n Combien de personnes sont ici présentes ? ");
        scanf("%d", &nbre_personnes);
     
            //ptr_prenom_personnes = malloc(sizeof(char*) * 50); // allocation des pointeurs sur les variables de type char
            ptr_prenom_personnes = malloc(sizeof(*ptr_prenom_personnes) * 50); // autre écriture de précédemment
     
            //ptr_age_personnes = malloc(sizeof(int*) *4);
            ptr_age_personnes = malloc(sizeof(*ptr_age_personnes) * 4);
     
     
            if (ptr_prenom_personnes == 0 || ptr_age_personnes == 0) // vérification de l'allocation de mémoire
            {
                return EXIT_FAILURE;
            }
     
            for (i = 0; i < nbre_personnes ; i++)
            {
                //ptr_prenom_personnes[i] = malloc(sizeof (char*) * 50); // création des tableaux qui contiendront les noms
                ptr_prenom_personnes[i] = malloc(sizeof(*ptr_prenom_personnes[i]) * 50);  // autre écriture de précédemment
     
                printf("\n Quel est le prénom de la personne %i ? ", i + 1);
                scanf("%s", ptr_prenom_personnes[i]);
            }
     
            for (i = 0; i < nbre_personnes ; i++)
            {
                printf("\n Quel âge a %s ? ", ptr_prenom_personnes[i]);
                scanf("%d", &ptr_age_personnes[i]);
            }
     
            for (i = 0; i < nbre_personnes ; i++)
            {
                printf("\n %s a %d an%c ", ptr_prenom_personnes[i], ptr_age_personnes[i], ptr_age_personnes[i] > 1 ? 's' : ' ');
            }
            // libération de la mémoire allouée ci-après
            for (i = 0; i < nbre_personnes; i++)
            {
                 free(ptr_prenom_personnes[i]); // libération de tous les prénoms renseignés
            }
     
            free(ptr_prenom_personnes);
            free(ptr_age_personnes);
     
            printf("\n");
     
        return EXIT_SUCCESS;
    }
    https://stackoverflow.com/questions/...or-0-from-main

    Je passerai le poste en résolue lorsque j'aurai réalisé l'allocation dynamique avec une structure, je tenterai ça demain matin...

    Encore merci pour vos lumières :-)

    Nicolas.

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

Discussions similaires

  1. [x86-64] Allocation dynamique (malloc) et heap
    Par xion.luhnis dans le forum x86 32-bits / 64-bits
    Réponses: 5
    Dernier message: 23/10/2010, 19h23
  2. Probleme d'allocation malloc free
    Par cmoibal dans le forum Linux
    Réponses: 1
    Dernier message: 23/05/2007, 14h21
  3. Réponses: 8
    Dernier message: 20/11/2006, 00h13
  4. Pb d'allocation dynamique avec malloc
    Par Magicmax dans le forum C
    Réponses: 5
    Dernier message: 12/12/2005, 01h04
  5. Réponses: 4
    Dernier message: 03/12/2002, 16h47

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