Répondre à la discussion
Affichage des résultats 1 à 17 sur 17

Allocation dynamique



  1. #1
    Titoune971

    Allocation dynamique


    ------

    Bonjour,

    Je voudrais une explication sur les allocations dynamiques. Je souhaite remplir un tableau d'abord à 1 dimension puis 2 (objectif final), avec les valeurs saisies par l'utilisateur mais mon programme ne fonctionne pas, il ne m' affiche pas le bon résultat (voir pièce jointe).

    Merci pour votre aide.

    Voici mon programme :
    Code:
    int remplir_tableau1D_dyn ()
    {
    int i, val, dim;
    int *tab=((int *)malloc(sizeof(tab)*dim)); 
    
    printf("Donnez la dimension de tab: ");
        scanf("%d", &dim);
        
    for(i=0;i<dim;i++)
        {
        printf("Donnez les valeurs de tab, val tab num %d : ",i);
        scanf("%d", &val);
        tab=val;
        }
    
    for(i=0;i<dim;i++)
        {
        printf("val tableau 1D dyn &tab= %d\n", &tab);
        printf("\n");
        }
    
    }
    
    int main (void)
    {
    printf("\n**********tab 1D dyn**********\n");
    remplir_tableau1D_dyn();
    while (1){};
    return 0;
    }

    Bonsoir Titoune971 et tout le groupe

    Pour être conforme à l'épinglé

    http://forums.futura-sciences.com/el...ointes-pj.html

    l'image pdf a été supprimée. Elle doit être présentée à nouveau, en extension jpg, gif ou png.

    .

    -----
    Dernière modification par gienas ; 20/01/2011 à 20h05. Motif: Supprimé image pdf

  2. Publicité
  3. #2
    Titoune971

    Re : Allocation dynamique

    La fonction remplir_tableau_1D est void pas int désolé.

  4. #3
    JPL
    Responsable des forums

    Re : Allocation dynamique

    Merci de poster la copie d'écran dans un format graphique : gif, png ou jpg.
    Rien ne sert de penser, il faut réfléchir avant - Pierre Dac

  5. #4
    Jack
    Modérateur

    Re : Allocation dynamique

    Code:
    int remplir_tableau1D_dyn ()
    {
    int i, val, dim;
    int *tab=((int *)malloc(sizeof(tab)*dim)); 
    
    printf("Donnez la dimension de tab: ");
        scanf("%d", &dim);
    Pour programmer, il faut un peu de bon sens: tu fais le malloc en définissant la taille du tableau à l'aide de la variable dim et ce n'est qu'après que tu définis la valeur de dim

    A+

  6. A voir en vidéo sur Futura
  7. #5
    invite765732342432
    Invité

    Re : Allocation dynamique

    Tout d'abord, tu fais ton malloc avant d'avoir initialisé dim... c'est mal barré.
    Ensuite, dans tes 2 boucles, tu utilises juste "val", sans indiquer la "case" du tableau que tu veux remplir
    Enfin, le while(1) en fin de programme est une drole d'idée...

  8. #6
    Jackyzgood

    Re : Allocation dynamique

    A vu d'oeil ça coince déjà à la 4eme ligne.

    IL FAUT TOUJOURS INITIALISER SES VARIABLES !!

    Ce n'est pas obligatoire, ma remarque n'est pas méchante mais elle t'évitera bien des problèmes !

    Code:
    int i, val, dim;
    int *tab=((int *)malloc(sizeof(tab)*dim));
    Quelles est la valeur de dim ? En réalité on en a aucune idée, lors du lancement du programme, il va demander au système d'exploitation la mémoire dont il a besoin, l'os va alors lui attribuer des adresses mémoire mais sans pour autant les vider de leur contenu !! Donc on peut se retrouver avec tout et n'importe quoi !

    Perso j'aurais fais un truc comme ça :

    Code:
    int i = 0, val = 0, dim = 1, *tab = NULL;
    
    printf("Donnez la dimension de tab: ");
        scanf("%d", &dim);
    
    tab=malloc(dim * sizeof(int));
    Je trouve que c'est plus propre d'utiliser
    Code:
    sizeof(int));
    plutôt que [code]sizeof(tab)/code] même si cela revient au même, car au moins on voit clairement de quel type il s'agit.

    Puis par la suite pour donner des valeurs au tableau il faut spécifier la "case" dans laquelle tu veux ranger l'information par exemple :
    Code:
    tab[i] = val
    Parce que sinon ça ne va pas coller et cela pour 2 raisons
    1) tu perd l'adresse de ton pointeur, donc plus de libération de mémoire possible
    2)les type int* et int ne sont pas identique, pas codé sur le même nombre d'octet, on va donc obtenir n'importe quoi si on essaye de faire passer ça.

    Dernière petite chose : ne pas oublier
    Code:
    free(tab)
    sinon la mémoire alloué à ce programme ne sera pas libéré et elle ne pourra pas être utilisé par un autre par la suite, ça s'appelle une fuite mémoire.
    si c'est idiot mais que ca marche, c'est que ce n'est pas idiot

  9. Publicité
  10. #7
    Titoune971

    Re : Allocation dynamique

    C bon j'ai trouvé la solution sa vien du malloc au lieu de :
    Code:
    int *tab=((int *)malloc(sizeof(tab)*dim));
    j'ai mis :
    Code:
    int *tab=((int *)malloc(sizeof(int)));
    et pour le printf, au lieu de:
    Code:
    printf("val tableau 1D dyn &tab= %d\n", &tab);
    J'ai mis :
    Code:
    printf("val tableau 1D dyn tab[i]= %d\n", tab[i]);
    et voila mon code fonctionne!!!

  11. #8
    Titoune971

    Re : Allocation dynamique

    J'arrange mon programme et je rajoute le free(tab).

    Merci

  12. #9
    invite765732342432
    Invité

    Re : Allocation dynamique

    Citation Envoyé par Jackyzgood Voir le message
    Je trouve que c'est plus propre d'utiliser sizeof(int));
    Justement, le problème c'est que si tu décides de passer à un long ou un char, le malloc devient faux alors que sinon, tout va bien (bon, c'est vrai que c'est pas fréquent... mais quand même !)

    Dernière petite chose : ne pas oublier
    Code:
    free(tab)
    sinon la mémoire alloué à ce programme ne sera pas libéré et elle ne pourra pas être utilisé par un autre par la suite, ça s'appelle une fuite mémoire.
    Euh... à la fin du process, la mémoire est libérée normalement.
    Cela dit, c'est clair que donner de bons réflexes dès le début est un plus !

  13. #10
    invite765732342432
    Invité

    Re : Allocation dynamique

    Citation Envoyé par Titoune971 Voir le message
    et voila mon code fonctionne!!!
    Non.
    Il parait fonctionner mais tu es en train d'écrire n'importe où dans la mémoire (le malloc de ton tablleau est toujorus faux).
    Segfault en vue !

  14. #11
    Titoune971

    Re : Allocation dynamique

    J'ai modifié le malloc et j'ai ajouter le free, mon code final est :
    Code:
    void remplir_tableau1D_dyn ()
    {
    int i, val, ligne=1;
    int *tab= NULL;
    
    printf("Donnez le nombre de ligne de tab: ");
        scanf("%d", &ligne);
    
    tab=((int*)malloc(ligne * sizeof(int)));
    for(i=0;i<ligne;i++)
        {
        printf("Donnez les valeurs de tab, val tab num %d : ",i);
        scanf("%d", &val);
        tab[i]=val;
        }
    printf("\n");
    
    for(i=0;i<ligne;i++)
        {
        printf("val tableau 1D dyn tab[i]= %d\n", tab[i]);
        }
    free(tab);
    }

  15. #12
    Jackyzgood

    Re : Allocation dynamique

    Citation Envoyé par Faith Voir le message
    Euh... à la fin du process, la mémoire est libérée normalement.
    Cela dit, c'est clair que donner de bons réflexes dès le début est un plus !
    D'après ce que j'ai lu, les variables allouée "normalement" genre :
    Code:
    int i =0;
    ne sont valable que dans la fonction dans laquelle elles sont, à la fin de la fonction la mémoire est automatiquement libéré.

    Pour les :
    Code:
    static int i =0;
    Il me semble que ce n'est qu'a la fin du programme que la mémoire est libéré automatiquement.

    Par contre pour malloc, qui est une allocation manuelle, la libération de la mémoire doit aussi se faire de manière manuelle. Il me semble qu'il existe un procédé appelé ramasse miette, qui permet de libérer les espaces mémoire que le programme n'utilise plus, mais je ne sais pas si on trouve ça sur le C.
    si c'est idiot mais que ca marche, c'est que ce n'est pas idiot

  16. Publicité
  17. #13
    invite765732342432
    Invité

    Re : Allocation dynamique

    Citation Envoyé par Jackyzgood Voir le message
    Par contre pour malloc, qui est une allocation manuelle, la libération de la mémoire doit aussi se faire de manière manuelle.
    En cours de programme, oui. Mais à la fin du programme, toute mémoire allouée (même par malloc) est systématiquement libérée (sauf cas particuliers de threads indépendants, etc)
    C'est l'OS qui gère cela.
    [edit] Et ce n'est pas une supposition, c'est un fait: j'ai codé quelques programmes qui bouffaient des Gigas de RAM, mais pouvaient être relancés un instant après sa fermeture

    Il me semble qu'il existe un procédé appelé ramasse miette, qui permet de libérer les espaces mémoire que le programme n'utilise plus, mais je ne sais pas si on trouve ça sur le C.
    Le Garbage Collector, c'est plutôt en java Et j'ai horreur de ça (mais c'est très personnel)
    Dernière modification par invite765732342432 ; 20/01/2011 à 17h19.

  18. #14
    Titoune971

    Re : Allocation dynamique

    Bonjour,
    j'ai refait mon programme avec plusieurs fonctions au lieu de tout mettre dans le main tout se passe bien sauf pour la libération de la mémoire.
    Je sais pas quoi faire.
    Le message est en pièce jointe.

    Merci pour votre aide.

    Voici le code :
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int declaration(int tab[][3])
    {
    int i, ligne;
    //int *tab[3]=NULL;
    printf("Donnez le nombre de ligne de tab: ");
    	scanf("%d", &ligne);
    
    /*********************************
    * Déclaration du tableau a 2D dyn*
    **********************************/
    tab=((int(*)[3])malloc(ligne * sizeof(int*)));
    if(tab==NULL) //test obligatoire
            {
                free(tab);    
    			printf("valeur inexistante\n");
            }
    
    return (*tab[3]);
    }
    
    
    int remplir_tableau2D_dyn (int tab[][3], int ligne)
    {
    /*************************************
    * Saisies valeurs du tableau a 2D dyn*
    **************************************/
    int i, j, val1=0, val2=0, val3=0;
    for(i=0;i<ligne;i++)
    	{
    	for(j=0;j<1;j++)
    		{
    		printf("Donnez les valeurs de tab, val tab num 1 : ");
    		scanf("%d", &val1);
    		tab[i][j]=val1;
    		printf("Donnez les valeurs de tab, val tab num 2 : ");
    		scanf("%d", &val2);
    		tab[i][j+1]=val2;
    		printf("Donnez les valeurs de tab, val tab num 3 : ");
    		scanf("%d", &val3);
    		tab[i][j+2]=val3;
    		}
    	}
    printf("\n");
    return (*tab[3]);
    }
    
    void affiche_tab_2D_dyn(int tab[][3], int ligne)
    {
    /*******************************
    * Affichage du tableau a 2D dyn*
    ********************************/
    int i, j;
    
    for(i=0;i<ligne;i++)
    	{
    	printf("val tableau 2D dyn ligne %d\n",i);
    	for(j=0;j<3;j++)
    		printf("tab[i][j]= %d\t", tab[i][j]);
    	printf("\n");
    	}
    }
    
    
    int main (void)
    {
    int ligne, i;
    int *tab[3]={NULL};
    printf("\n**********tab 2D dyn**********\n");
    declaration(tab);
    remplir_tableau2D_dyn(tab,ligne);
    affiche_tab_2D_dyn(tab, ligne);
    
    //Libération de la mémoire
    /********************
    PROBLEME
    *********************
    for(i=0;i<ligne;i++)
    	free(tab[i]);
    free(tab);
    
    ou
     free(tab);
    */
    
    while (1){};
    return 0;
    }
    Images attachées Images attachées  

  19. #15
    Jackyzgood

    Re : Allocation dynamique

    Pas très claire le message de windown ....

    Il y a un truc qui ne me plais pas la dedans :

    Code:
    int declaration(int tab[][3])
    {
    ...
    tab=((int(*)[3])malloc(ligne * sizeof(int*)));
    Je ne sais pas trop ce que ça donne un truc comme ça ... La fonction malloc renvoie un pointeur et je ne sais pas si il est possible d'alloué, ou plutôt de réallouer, un pointeur qui à été alloué automatiquement. En tout cas ça ne peut rien donner de bon...

    Si tu veux déporter l'allocation dynamique dans une fonction il faut alors qu'elle prenne en paramètre un pointeur de pointeur.

    Explication :

    Un variable est limitée, elle ne peut pas "sortir" de la fonction dans laquelle elle a été déclaré, ça s'appelle la porté de la variable.

    Exemple :
    Code:
    void fonction_test(int variable_test)
    {
       variable_test *= 3;
    }
    Dans ce cas là, lors de l'appel de cette fonction une copie du paramètre va être envoyé à la fonction et cette copie sera détruite à la fin de cette fonction. Pour faire "sortir" la valeur de la fonction on peut par exemple faire :

    Code:
    int fonction_test(int variable_test)
    {
       return variable_test * 3;
    }
    La fonction renverra alors la valeur du calcul effectué. Mais il y a une autre façon, qui elle permet d'effectuer plusieurs calculs sur plusieurs variables et d'en récupérer les résultat, c'est l'utilisation de pointeur :

    Code:
    void fonction_test(int *pointeur_test)
    {
       *pointeur_test *= 3;
    }
    A ce moment là, ce n'est plus une copie de la variable qui est faite, mais une copie de l'adresse de cette variable ! Ce qui va tout changer, car s'il y a bien un pointeur qui est créé puis détruit, la variable dont on a envoyé l'adresse à la fonction ne le sera pas. On demande en fait à la fonction d'aller modifier la valeur à une certaine adresse.

    Maintenant revenons à notre malloc, imaginons le cas suivant :
    Code:
    int fonction_test(int *pointeur_test)
    {
       pointeur_test = malloc( 3 * sizeof(int));
    }
    Que va-t-il se passer ? Un pointeur sera crée, une copie de l'adresse sera effectuée, puis cette adresse sera modifié, dirigé vers une autre zone mémoire et comme d'habitude à la fin de la fonction, les variables sont effacées ... donc on a perdu notre pointeur et la zone mémoire vers laquelle il pointait ...

    Il faut donc faire comme dans l'exemple précédant, demander à la fonction de modifier le contenue d'une adresse. Mais ce qu'on cherche à faire c'est modifier une adresse, il nous faut donc un pointeur vers cette adresse, un pointeur de pointeur.

    Code:
    int fonction_test(int **pointeur_de_pointeur_test)
    {
       *pointeur_de_pointeur_test = malloc( 3 * sizeof(int));
    }
    Si on veut accéder à un élément du tableau dans cette fonction on ne peut pas se contenter de :
    Code:
       *pointeur_de_pointeur_test[i];
    Ca ne marchera tout simplement pas, car si on y regarde de plus près :
    *pointeur_de_pointeur_test est le premier élément du tableau (indice 0 : [0]), pour avoir la première case il faut alors regarder la case mémoire suivante et donc faire :

    Code:
       *pointeur_de_pointeur_test + 1;
    Donc pour obtenir la valeur d'une case de ce tableau il faut faire :

    Code:
       *(*pointeur_de_pointeur_test + i);
    et on aura alors accès à la ième case du tableau.
    si c'est idiot mais que ca marche, c'est que ce n'est pas idiot

  20. #16
    Titoune971

    Re : Allocation dynamique

    J'ai essayé d'appliquer ce que tu viens de m'expliquer mais ça ne fonctionne pas. Je pense que je me suis trompé, es ce que tu peux regarder stp.
    Le problème est signalé lors de la saisie des valeurs du tableau.
    Il me dit :

    0xC0000005: Violation d'accès lors de la lecture de l'emplacement 0x00000000

    Merci.
    voici mon code modifié:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int declaration()
    {
    int ** tab=NULL;
    int ligne;
    printf("Donnez le nombre de ligne de tab: ");
    	scanf("%d", &ligne);
    
    /*********************************
    * Déclaration du tableau a 2D dyn*
    **********************************/
    *tab=((int*)malloc(ligne * sizeof(int*)));
    if(tab==NULL) //test obligatoire
            {
               free(tab);    
    			printf("valeur inexistante\n");
            }
    	/*for(i=0;i<3;i++)
    	tab[i]=((int*) malloc(3 * sizeof (int*)));
    			if(tab[i]==NULL) 
    					{
    						for(i=i-1; i>=0; i--)
    							free(tab[i]);
    						free(tab);
    						printf("valeur inexistante\n");
    					}*/
    return (**tab);
    }
    
    
    int remplir_tableau2D_dyn (int **tab, int ligne)
    {
    /*************************************
    * Saisies valeurs du tableau a 2D dyn*
    **************************************/
    int i, j, val1=0, val2=0, val3=0;
    for(i=0;i<ligne;i++)
    	{
    	for(j=0;j<1;j++)
    		{
    		printf("Donnez les valeurs de tab, val tab num 1 : ");
    		scanf("%d", &val1);
    /********************
    PROBLEME : en mode pas à pas il s'arrete là
    *********************/
    		*(*tab + i)=val1;
    		printf("Donnez les valeurs de tab, val tab num 2 : ");
    		scanf("%d", &val2);
    		*(*tab + i+1)=val2;
    		printf("Donnez les valeurs de tab, val tab num 3 : ");
    		scanf("%d", &val3);
    		*(*tab + i+2)=val3;
    		}
    	}
    printf("\n");
    return (**tab);
    }
    
    void affiche_tab_2D_dyn(int **tab, int ligne)
    {
    /*******************************
    * Affichage du tableau a 2D dyn*
    ********************************/
    int i, j;
    
    for(i=0;i<ligne;i++)
    	{
    	printf("val tableau 2D dyn ligne %d\n",i);
    	for(j=0;j<3;j++)
    		printf("tab[i][j]= %d\t", *(*tab + j));
    	printf("\n");
    	}
    }
    
    
    int main (void)
    {
    int ligne, i;
    int **tab=NULL;
    printf("\n**********tab 2D dyn**********\n");
    declaration();
    remplir_tableau2D_dyn(tab,ligne);
    affiche_tab_2D_dyn(tab, ligne);
    
    //Libération de la mémoire
    /********************
    PROBLEME
    *********************/
    for(i=0;i<ligne;i++)
    	free(tab[i]);
    free(tab);
    /*
    ou
     free(tab);
     */
    while (1){};
    return 0;
    }

  21. #17
    Jackyzgood

    Re : Allocation dynamique

    Ta fonction déclaration ne prend aucun paramètre. Tu crée le tableau à l'intérieur, si tu ne récupère pas son adresse il sera perdu.

    Code:
    return (**tab);
    Ne fait que renvoyer la valeur contenue dans la première case du tableau, pas son adresse. Donc tu perds toute trace de ce que tu as crée dans cette fonction, finalement elle ne sert à rien ...

    Si tu veux que ton tableau soit plus facile d'accès il faut également penser aux colones.
    si c'est idiot mais que ca marche, c'est que ce n'est pas idiot

Discussions similaires

  1. problème insertion fichier .txt dans une allocation dynamique
    Par Ptitsuisse91 dans le forum Programmation et langages, Algorithmique
    Réponses: 9
    Dernier message: 09/01/2011, 18h32
  2. [language C]Allocation mémoire.
    Par piwi dans le forum Logiciel - Software - Open Source
    Réponses: 4
    Dernier message: 05/07/2010, 08h33
  3. allocation dynamique c/c++
    Par Lt972 dans le forum Logiciel - Software - Open Source
    Réponses: 2
    Dernier message: 16/06/2008, 13h19
  4. Dérogation Allocation de Recherche
    Par Reace dans le forum Orientation après le BAC
    Réponses: 6
    Dernier message: 11/12/2007, 15h58