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 ne fonctionne qu une fois.


Sujet :

C

  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2006
    Messages : 7
    Points : 4
    Points
    4
    Par défaut allocation dynamique ne fonctionne qu une fois.
    Bonjour.
    dans le cadre de mes études je dois réaliser un petit programme qui doit pouvoir allouer un nombre de float dynamiquement: nombre d'élément lu par un scanf. Toutes les données en entrées sont en redirection vers un fichiers de données.
    Celui ci est de blocs constitués comme suit.
    Première ligne : int code int n(nombre d'élement)
    deuxième ligne: suite de n float que je dois stocker dynamiquement
    et ainsi de suite.
    voici le code de mon 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
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
     
    #include<stdio.h>
    #include<math.h>
    #include<malloc.h>
     
    float * alloc_mem(int n);
    void liberer_mem(float *x);
    void lecture( float *x, float *y, int n);
    void liberer_mem(float *tab)
    {
    	free(tab);
    }
     
    float * alloc_mem(int n)
    {
    	float *temp;
    	temp=(float*)malloc(n*sizeof(float));
    	return temp;
    }
     
    void lecture( float *x, float *y, int n)
    {
    	int i=0;
    	for(i=0;i<n;i++)
    	{
    		scanf("%f %f",x+(i*sizeof(float)),y+(i*sizeof(float)));
    		printf("je lis\n");
    	}
    }
    void impression(float *tab, int n)
    {
    	int i=0;
    	for(i=0;i<n;i++)
    	{
    		if(i%5==0)
    			printf("\n");
    		printf("%2.3f | ",*(tab+(i*sizeof(float))));
    	}
    }
     
     
    int main (void)
    {
     
    	int code, n, i=1;
    /*x et y représentent en fait un nuage de point*/
    	float *x, *y;
    	while(scanf("%d %d",&code,&n)==2)
    	{
    	printf("n=%d\n",n);
    	printf("nuage%d .\n",i);
    	printf("**********\n");
    	printf("est ce quez j arrive la?");
     
    	if((x=alloc_mem(n))==NULL)
    		printf("erreur sur l allocation\n");
     
     
    	printf("%p\n",x);
    	printf("jalloue la mémoire");
    	y=alloc_mem(n);
    	lecture(x,y,n);
    	printf("impression de x\n");
    	impression(x,n);
    	printf("impression de y\n");
    	impression(y,n);
    	liberer_mem(x);
    	liberer_mem(y);
    	printf("%p\n",x);
    	printf("\n");
    	i++;
    	}
    	return 0;
    }
    et le fichier de données
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    1 10
    1.52 2.52 1.21 5.52 6.52 9.32 1.25 5.65 9.32 4.36 12.32 3.65 4.95 1.75 5.25 2. 32.3 33.6 12. 32.3
    1 5
    2.25 21.32 5. 21.78 5.256 21.54 1.25 1.65 2.65 58.95
    1 10
    1.52 2.52 1.21 5.52 6.52 9.32 1.25 5.65 9.32 4.36 12.32 3.65 4.95 1.75 5.25 2. 32.3 33.6 12. 32.3
    1 5
    2.25 21.32 5. 21.78 5.256 21.54 1.25 1.65 2.65 58.95
    Voici maintenant le résultat de l'exécution.
    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
     
    n=10
    nuage 1 .
    **********
    est ce quez j arrive la?003D24B8
    jalloue la mÚmoireje lis
    je lis
    je lis
    je lis
    je lis
    je lis
    je lis
    je lis
    je lis
    je lis
     
    impression du tableau x
     
    1.520 | 1.210 | 6.520 | 1.250 | 9.320 |
    12.320 | 4.950 | 5.250 | 32.300 | 12.000 |
    impression du tableau y
     
    1.250 | 9.320 | 12.320 | 4.950 | 5.250 |
    32.300 | 12.000 | 2.000 | 33.600 | 32.300 | 003D24B8
     
    n=5
    nuage 2 .
    **********
    est ce quez j arrive la?
    toute les impression qui n ont rien a voir sont la pour tester jusqu'ou je peux aller dans le code.
    Apparement le programme s'arrete après l'allocation la deuxième fois, je ne comprend pas pourquoi...
    Pöurriez vous m'expliquer pourquoi?
    D'avance Merci.

  2. #2
    Expert éminent
    Avatar de PRomu@ld
    Homme Profil pro
    Ingénieur de Recherche
    Inscrit en
    Avril 2005
    Messages
    4 155
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Ingénieur de Recherche
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2005
    Messages : 4 155
    Points : 6 486
    Points
    6 486
    Par défaut
    Juste pour info à la compilation ça me donne ça :

    test.c:3:20: error: malloc.h: No such file or directory
    test.c: In function 'liberer_mem':
    test.c:10: error: implicit declaration of function 'free'
    test.c:10: warning: nested extern declaration of 'free'
    test.c: In function 'alloc_mem':
    test.c:16: error: implicit declaration of function 'malloc'
    test.c:16: warning: incompatible implicit declaration of built-in function 'malloc'
    test.c: At top level:
    test.c:30: warning: no previous prototype for 'impression'
    J'aimerai que tu m'explique comment tu fais pour exécuter ton programme puisqu'il ne compile pas.

    D'autre part, ceci est déprécié :

    temp=(float*)malloc(n*sizeof(float));
    il vaut mieux faire ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    temp= malloc(n*sizeof(float));
    De plus, tu ne testes pas toujours les valeur de retour de ta fonction (tu le fais pour x mais pas pour y)

    Pour ton free, la bonne méthode pour libérer la mémoire c'est de faire ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    free(tab);
    tab = NULL;
    Or attention cependant si tu utilises ta fonction telle que tu l'a faite, ça ne marchera pas.

    Il faut faire ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    void liberer_mem( float ** tab )
    {
         free(*tab);
         *tab = NULL;
    }
    et lors de l'appel il faut faire ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    liberer_mem( &tab );
    L'explication vient du type de passage des paramètres des fonctions en C.

    Enfin, pour tes debuggages, utilise un fprintf sur la sortie d'erreur standard, du coup tu sauras exactement où ça plante ( problème de bufferisation).

    Je n'ai pas répondu exactement à ta question mais corrige un petit peu ton code (du moins pour qu'il compile chez moi ...) et ensuite je pourrais surement t'aider.

  3. #3
    Candidat au Club
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2006
    Messages : 7
    Points : 4
    Points
    4
    Par défaut
    J'utilise MinGW developer studio. ici je n ai pas d erreur de compilation. est ce que vous pourriez , svp , m expliquer le prototype de la fonction liberer_mem? et l'appel surtout car je ne comprend pas.
    voici mon code modifié avec ajout de la librairie stdlib.h. Je m'excuse pour les erreurs que je n'ai pas eu...
    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
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
     
    #include<stdio.h>
    #include<math.h>
    #include<stdlib.h>
     
    float * alloc_mem(int n);
    void liberer_mem(float **tab);
    void lecture( float *x, float *y, int n);
    void liberer_mem(float **tab)
    {
     
    	free(*tab);
    	*tab=NULL;
    }
     
    float * alloc_mem(int n)
    {
    	float *temp;
    	temp=(float*)malloc(n*sizeof(float));
    	return temp;
    }
     
    void lecture( float *x, float *y, int n)
    {
    	int i=0;
    	for(i=0;i<n;i++)
    	{
    		scanf("%f %f",x+(i*sizeof(float)),y+(i*sizeof(float)));
    		printf("je lis\n");
    	}
    }
    void impression(float *tab, int n)
    {
    	int i=0;
    	for(i=0;i<n;i++)
    	{
    		if(i%5==0)
    			printf("\n");
    		printf("%2.3f | ",*(tab+(i*sizeof(float))));
    	}
    }
     
     
    int main (void)
    {
     
    	int code, n, i=1;
    	float *x, *y;
    	while(scanf("%d %d",&code,&n)==2)
    	{
    	printf("n=%d\n",n);
    	printf("nuage %d .\n",i);
    	printf("**********\n");
    	printf("est ce quez j arrive la?");
     
    	if((x=alloc_mem(n))==NULL  || (y=alloc_mem(n))==NULL )
    	printf("erreur sur l allocation\n");
     
    	printf("%p\n",x);
    	printf("jalloue la mémoire");
    	lecture(x,y,n);
    	printf("\nimpression du tableau x\n");
    	impression(x,n);
    	printf("\nimpression du tableau y\n");
    	impression(y,n);
    	free(x);
    	free(y);
    	liberer_mem(&x);
    	liberer_mem(&y);
    	printf("%p\n",x);
    	printf("\n");
    	i++;
    	}
    	return 0;
    }
    Le résultat est toujours le meme. Je n'ai pas eu plus de résultats
    Pour rappel du résultat :
    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
     
     
    n=10
    nuage 1 .
    **********
    est ce quez j arrive la?003D24B8
    jalloue la mÚmoireje lis
    je lis
    je lis
    je lis
    je lis
    je lis
    je lis
    je lis
    je lis
    je lis
     
    impression du tableau x
     
    1.520 | 1.210 | 6.520 | 1.250 | 9.320 |
    12.320 | 4.950 | 5.250 | 32.300 | 12.000 |
    impression du tableau y
     
    1.250 | 9.320 | 12.320 | 4.950 | 5.250 |
    32.300 | 12.000 | 2.000 | 33.600 | 32.300 | 003D24B8
     
    n=5
    nuage 2 .
    **********
    est ce quez j arrive la?
    Merci d'avance

  4. #4
    Expert éminent
    Avatar de PRomu@ld
    Homme Profil pro
    Ingénieur de Recherche
    Inscrit en
    Avril 2005
    Messages
    4 155
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Ingénieur de Recherche
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2005
    Messages : 4 155
    Points : 6 486
    Points
    6 486
    Par défaut
    Alors, en C, les fonctions passent leur paramètres par copie, ainsi lorsque tu fais ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    void fct( int a, int b)
    {
    ...
    }
    Tu es d'accord que a et b lors des appels sont des copies des variables que tu as passé en paramètre.

    Pour le cas de pointeurs dans les paramètres tu fais ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    void fct( int *a )
    {
         ...
    }
    Le pointeur a est une copie du pointeur que tu as passé en paramètre. Comme il s'agit de pointeurs, tout ce que tu vas modifier en passant par a modifiera aussi ce qui sera pointé par ce que tu as passé en paramètre. Ca, je pense que tu l'as bien compris au vu de ton code.

    Maintenant venons en au point délicat. Lorsque tu fais :
    Tu mets le pointeur a à NULL et pas la variable pointée, en effet pense à ce qui se passe lorsque tu fais ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    int * p1;
    int * p2;
    int var;
     
    p1 = &var;
    p2 = p1;
     
    free(p2);
    p2 = NULL;
    A ton avis que vaut p1 ? et bien en fait, p1 ne vaut pas NULL. Et c'est exactement ce qui se passait lorsque tes paramètres étaient passés par un simple pointeur.

    Si tu veux t'en convaincre teste ce petit programme. et regarde le résultat.

    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
     
    #include <stdlib.h>
    #include <stdio.h>
     
    int main ()
    {
      int var,*p1,*p2;
     
      p1 = &var;
      p2 = p1;
     
      free(p2);
      p2 = NULL;
     
      printf("p1 = %p\n",p1);
      printf("p2 = %p\n",p2);
     
      return EXIT_SUCCESS;
    }
    Maintenant, lorsque tu fais ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    void fct (int **a )
    Tu as donc un pointeur sur un pointeur d'entier, et lors de l'appel, tu modifie bien aussi le pointeur que tu as passé. Ceci est du au fait que le compilateur va copier ce pointeur de pointeur et aussi au fait que nous modifions le pointeur le plus interne (donc que l'on travaille avec *a ).

    Reprenons le même programme que tout à l'heure :

    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
     
    #include <stdlib.h>
    #include <stdio.h>
     
    int main ()
    {
      int var,*p1,**p2;
     
      p1 = &var;
      p2 = &p1;
     
      free(*p2);
      *p2 = NULL;
     
      printf("p1 = %p\n",p1);
      printf("p2 = %p\n",*p2);
     
      return EXIT_SUCCESS;
    }
    Maintenant, p1 vaut bien NULL comme nous le voulions. Il en est donc de même avec la fonction libere_mem

  5. #5
    Candidat au Club
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2006
    Messages : 7
    Points : 4
    Points
    4
    Par défaut
    Merci beaucoup pour les explications.
    mais est ce que vous pouvez comprendre les résultats de mon code???
    Pouvais vous me dire ce qui ne va pas?
    Histoire d'avoir une piste pour chercher.$
    Merci

  6. #6
    Rédacteur/Modérateur
    Avatar de Trap D
    Profil pro
    Inscrit en
    Septembre 2003
    Messages
    4 942
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2003
    Messages : 4 942
    Points : 6 498
    Points
    6 498
    Par défaut
    Ton erreur provient d'une mauvaise compréhension de l'arithmétique des pointeurs :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ",*(tab+(i*sizeof(float))
    Comme le compilateur connaît le type de tab, float, il calcule automatiquement la taille du décalage pour passer d'un float à l'autre dans le tableau et toi tu le trompes avec tes produits par sizeof(float).
    Donc il faut enlever tous les *sizeof(float) dans les indiçages de tableau.
    "La haine seule fait des choix" - Koan Zen
    "Il ne faut pas être meilleur que les autres, il faut être meilleur que soi." Albert Jacquard
    "Ceux qui savent où ils ont posé leur parapluie ne sont pas alcooliques." - pgibonne.
    Faites du Prolog, ça vous changera les idées !
    Ma page Prolog
    Mes codes sources commentés

    Mon avatar : La Madeleine à la veilleuse de Georges de La Tour

  7. #7
    Candidat au Club
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2006
    Messages : 7
    Points : 4
    Points
    4
    Par défaut
    Un grand merci. c'etait bien les sizeof qui faisait foirait tout le bazar... ma dernière question sera donc dans quel cas les utilise t-on?
    Merci encore...

  8. #8
    Rédacteur/Modérateur
    Avatar de Trap D
    Profil pro
    Inscrit en
    Septembre 2003
    Messages
    4 942
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2003
    Messages : 4 942
    Points : 6 498
    Points
    6 498
    Par défaut
    Ben, pour les allocations mémoires par exemple, pour les recopies de données, quand on est obligé de travaillé au niveau byte.
    "La haine seule fait des choix" - Koan Zen
    "Il ne faut pas être meilleur que les autres, il faut être meilleur que soi." Albert Jacquard
    "Ceux qui savent où ils ont posé leur parapluie ne sont pas alcooliques." - pgibonne.
    Faites du Prolog, ça vous changera les idées !
    Ma page Prolog
    Mes codes sources commentés

    Mon avatar : La Madeleine à la veilleuse de Georges de La Tour

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

Discussions similaires

  1. CoverFlow et contenu dynamique . ne fonctionne qu'une fois
    Par faverotconception dans le forum Silverlight
    Réponses: 8
    Dernier message: 05/10/2009, 21h07
  2. On Error GoTo qui ne fonctionne qu'une fois
    Par bernard0828 dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 23/08/2007, 07h39
  3. bouton submit qui ne fonctionne qu'une fois
    Par sam01 dans le forum Langage
    Réponses: 6
    Dernier message: 06/07/2007, 08h19
  4. [AJAX] Méthode sous Ajax qui ne fonctionne qu'une fois?
    Par patrice419 dans le forum Général JavaScript
    Réponses: 2
    Dernier message: 13/04/2007, 13h19
  5. Réponses: 2
    Dernier message: 26/06/2006, 13h43

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