Polynômes, dépassement de mémoire

Polynômes, dépassement de mémoire - C - Programmation

Marsh Posté le 04-06-2008 à 21:09:07    

Bonjour,
 
Je réalise un programme en C qui réalise des opérations sur des polynômes définis tels que :

Code :
  1. typedef unsigned int uint; 
  2. struct Polynome                   /*On définit la structure polynome                      */
  3. {
  4.         uint Degre;                  /* Un entier non signé pour le degré            */
  5.         double *Coefficients;  /* Un tableau de double pour les coefficients   */
  6. };


La plupart des fonctions fonctionnent (enregistrement d'un polynome, chargement à partir d'un fichier binaire, lecture d'un fichier binaire, calcul en x=?, dérivé, etc...).
 
J'ai cependant un problème lorsque je calcul le signe avec ma fonction double Eval(struct Polynome *p, double x) qui me calcul la valeur du polynôme en un point.
J'utilise la fonction Roots pour calculer approximativement quand le polynôme s'annule. Cette fonction fait appel à Eval et il n'y a pas de problèmes. Cependant lorsque j'appelle de nouveau Eval dans une autre fonction, ça plante. Eval veut lire un polynôme à une adresse nulle... Pourquoi ?
La fonction Sign prend "mal" mon polynome en argument (Breakpoint 1, Sign (p=0x0, x1=-5, x2=5) at aau.c:242), Pourquoi ?
 
Le programme est compilé avec ces options :  gcc -g aau.c -o aau -lm -Wall
La sortie du gdb :

Code :
  1. Starting program: /home/yoyo/c/aau/aau
  2. Groupe2
  3. ############
  4. On declare un polynome p1
  5. On declare un polynome p2 demande à l'utilisateur
  6. Quel est le degre du polynome ? : 2
  7. Coefficient 0 : 2
  8. Coefficient 1 : 3
  9. Coefficient 2 : -2
  10. On declare un polynome p3 charge a partir d'un fichier
  11. 1.000000 + 2.000000 x + 3.000000 x^2 + 4.000000 x^3 + 5.000000 x^4 + 6.000000 x^5
  12. On declare un polynome p4=p1*p2
  13. 4.000000 + 12.000000 x + 1.000000 x^2 - 12.000000 x^3 + 4.000000 x^4
  14. ########f(-0.500000)=0.000000 out[0]=-0.500000
  15. ########f(2.000000)=-0.000000 out[1]=2.000000
  16. On affiche le signe de p4 sur [-5;5]
  17. Breakpoint 1, Sign (p=0x0, x1=-5, x2=5) at aau.c:242
  18. 242  out[N]=Roots(p,x1,x2,out);
  19. (gdb) s
  20. Roots (p=0x0, x1=-5, x2=5, out=0xbf8c4fc8) at aau.c:186
  21. 186  int n=0;
  22. (gdb) s
  23. 187     int signe=0,signeavant=0,j;
  24. (gdb) s
  25. 188     double i=0.;
  26. (gdb) s
  27. 189     if(Eval(p,x1)>0)
  28. (gdb) s
  29. Eval (p=0x0, x=-5) at aau.c:175
  30. 175  double out=0;
  31. (gdb) s
  32. 177  for(i=0;i<=p->Degre;i++)
  33. (gdb) s
  34. Program received signal SIGSEGV, Segmentation fault.
  35. 0x08048a31 in Eval (p=0x0, x=-5) at aau.c:177
  36. 177  for(i=0;i<=p->Degre;i++)
  37. (gdb) print p
  38. $1 = (struct Polynome *) 0x0
  39. (gdb)


 
Le programme :

Code :
  1. /*  
  2. *  
  3. * Groupe 2
  4. * Vim 7.1.138
  5. * gcc 4.2.3
  6. */
  7. #include <stdio.h>             /*On inclue les librairies standards  */
  8. #include <math.h>
  9. #include <stdlib.h>
  10. #include <float.h>
  11. #define N 100
  12. typedef unsigned int uint;           /*On définit les entiers non signés par uint*/
  13. struct Polynome              /*On définit la structure polynome   */
  14. {
  15. uint Degre;              /* Un entier non signé pour le degré  */
  16. double *Coefficients;           /* Un tableau de double pour les coefficients */
  17. };
  18. // Fonctions donnees
  19. double Pow(double x, uint p);
  20. struct Polynome *Allocate(unsigned int degre);
  21. void Delete(struct Polynome *p);
  22. void Display(struct Polynome *p);
  23. struct Polynome *Multiply(struct Polynome *p1, struct Polynome *p2);
  24. // Fonctions a completer
  25. struct Polynome *Prompt(void);
  26. struct Polynome *Load(char *filename);
  27. void Save(struct Polynome *p, char *filename);
  28. double Eval(struct Polynome *p, double x);
  29. uint Roots(struct Polynome *p, double x1, double x2, double *out);
  30. struct Polynome *Derivate(struct Polynome *p);
  31. void Sign(struct Polynome *p, double x1, double x2);
  32. void Variation(struct Polynome *p, double x1, double x2);
  33. double Eval(struct Polynome *p, double x)
  34. {
  35. double out=0;
  36. int i;
  37. for(i=0;i<=p->Degre;i++)
  38. {
  39.  out=out+p->Coefficients[i]*pow(x,(float)i);
  40. }
  41. return out;
  42. }
  43. uint Roots(struct Polynome *p, double x1, double x2, double *out)
  44. {
  45. int n=0;
  46.     int signe=0,signeavant=0,j;
  47.     double i=0.;
  48.     if(Eval(p,x1)>0)
  49.         signeavant=1;
  50.     else
  51.         signeavant=0;
  52. for(j=0;j<N;j++)
  53.  out[j]=0.0;
  54.     for(i=x1+0.0000001;i<x2;i+=0.0000001)
  55.     {
  56.  if(Eval(p,i)>0)
  57.   signe=1;
  58.     else
  59.         signe=0;
  60.     if(signeavant!=signe)
  61.     {  
  62.   out[n]=i;
  63.   printf("########f(%lf)=%lf out[%d]=%lf\n",i,Eval(p,i),n,out[n]);
  64.   n++;
  65.  }
  66.  //printf("#f(%lf)=%lf ; signeavant=%dsigne=%d\n",i,Eval(p,i),signeavant,signe);
  67.     signeavant=signe;
  68. }
  69. /*for(j=0;j<N;j++)
  70. {
  71.  printf("sol[%d]=%lf\n",j,out[j]);
  72. }*/
  73.     return out[100];
  74. }
  75. void Sign(struct Polynome *p, double x1, double x2)
  76. {
  77. double out[N];
  78. out[N]=Roots(p,x1,x2,out);
  79. }
  80. int main(int argc, char **argv)
  81. {
  82. printf("\n\nGroupe2\n############\n" );
  83. printf("On declare un polynome p1\n" );
  84. struct Polynome *p1;
  85. p1=Allocate(2);
  86. p1->Degre=2;
  87. p1->Coefficients[0]=2;
  88. p1->Coefficients[1]=3;
  89. p1->Coefficients[2]=-2;
  90. printf("On declare un polynome p2 demande à l'utilisateur\n" );
  91. struct Polynome *p2;
  92. p2=Prompt();
  93. printf("On declare un polynome p3 charge a partir d'un fichier\n" );
  94. struct Polynome *p3;
  95. p3=Load("aau.dat" );
  96. Display(p3);
  97. printf("On declare un polynome p4=p1*p2\n" );
  98. struct Polynome *p4;
  99. p4=Allocate((p1->Degre)+(p2->Degre));
  100. p4=Multiply(p1,p2);
  101. Display(p4);
  102. double out[N];
  103. //int i;
  104. out[N]=Roots(p1,-3,3,out);
  105. /*for(i=0;i<N;i++)
  106. {
  107.  printf("Racine %d : %lf\n",i,sol[i]);
  108. }*/
  109. printf("\nOn affiche le signe de p4 sur [-5;5]\n" );
  110. Sign(p4,-5,5);
  111. Delete(p1);
  112. Delete(p2);
  113. Delete(p3);
  114. Delete(p4);
  115. return 0;
  116. }


 
Edit : c'ets vrai c'était un peu long...  
 


Message édité par 2xyo le 04-06-2008 à 21:25:38

---------------
2 * yo = yoyo
Reply

Marsh Posté le 04-06-2008 à 21:09:07   

Reply

Marsh Posté le 04-06-2008 à 21:14:38    

T'avais pas plus long à nous faire lire ?
 
Et si tu sabrais tout ce qui ne change rien au problème et que tu nous montrais le code complet le plus simple qui provoque le problème ?

Reply

Marsh Posté le 04-06-2008 à 22:15:28    

Ton code est imbitable, buffer overflow, tableau inutile, indentation bordélique, pas étonnant que tu passes des heures à débugger ce foutoir.
 
Pour info, ton erreur se situe certainement à la ligne 128 :
 

Code :
  1. double out[N];
  2. out[N]=Roots(p1,-3,3,out);


 
En déclarant ton tableau de N cases et affectant dans la N+1 ème case, tu écrase en fait la variable locale précendante de ton programme (du fait que sur la pile les variables sont empilés les unes sur les autres) qui est ... ton pointeur p4.
 
Par un concours de cirsconstance que j'ignore, mais à ce niveau on s'en tape, p4 se retrouve initialisé à 0, valeur transmise à Sign, puis transmise à Eval, puis ... SEGFAULT.

Message cité 1 fois
Message édité par tpierron le 04-06-2008 à 22:18:06
Reply

Marsh Posté le 04-06-2008 à 22:44:04    

tpierron a écrit :

Ton code est imbitable, buffer overflow, tableau inutile, indentation bordélique, pas étonnant que tu passes des heures à débugger ce foutoir.


La structure du code nous a été fournie par nos professeurs :p. (J'ai évidement ajouté pas mal de bordel). L'indentation, c'est le copier coller qui a foiré...
 

tpierron a écrit :


Pour info, ton erreur se situe certainement à la ligne 128 :
 

Code :
  1. double out[N];
  2. out[N]=Roots(p1,-3,3,out);


 
En déclarant ton tableau de N cases et affectant dans la N+1 ème case, tu écrase en fait la variable locale précendante de ton programme (du fait que sur la pile les variables sont empilés les unes sur les autres) qui est ... ton pointeur p4.
 
Par un concours de cirsconstance que j'ignore, mais à ce niveau on s'en tape, p4 se retrouve initialisé à 0, valeur transmise à Sign, puis transmise à Eval, puis ... SEGFAULT.


 
Je vais méditer ça, mais je n'ai pas très bien compris à première vue comment y remédier... Je repasse dans une heure ou deux :sleep:  
P.S : J'ai eu en consigne :

Citation :

uint Roots(struct Polynome *p, double x1, double x2, double *out)
Les racines seront stockées dans le tableau dont l'adress out est également passée en paramètre et dont l'allocation statique aura été faite ailleurs que dans cette fonction. cette fonction retournera le nombre de racines effectivement trouvées dans l'intervalle


 
P.S 2 : J'ai un problème en ammont qui n'arrange pas les choses :

Code :
  1. On affiche le signe de p4 sur [-5;5]
  2. ########f(-0.500000)=0.000000 out[0]=-0.500000
  3. ########f(-0.499990)=0.000000 out[1]=-0.499990
  4. ########f(2.000000)=0.000000 out[2]=2.000000
  5. ########f(2.000010)=0.000000 out[3]=2.000010
  6. Segmentation fault


Je viens juste de me rappeler à peu prêt comment on compare des float....Et je n'avais pas fait comme ça...


---------------
2 * yo = yoyo
Reply

Marsh Posté le 04-06-2008 à 23:33:26    

J'ai changé quelques petits trucs tel que :
Le calcul des valeurs en 0 :

Code :
  1. uint Roots(struct Polynome *p, double x1, double x2, double *out)
  2. {
  3.     int n=0;
  4.     double i;
  5.     for(i=x1+0.00001;i<=x2;i+=0.00001)
  6.     { 
  7.         if(fabs(Eval(p,i))<=fabs(Eval(p,i))*FLT_MIN){
  8.             out[n]=i;
  9.             printf("#f(%lf)=%lf out[%d]=%lf\n",i,Eval(p,i),n,Eval(p,i));
  10.             n++;
  11.         }
  12.     } 
  13.     return out[100];
  14. }


L'appel de mes fonctions dans le main

Code :
  1. double out[N];
  2.     out[N]=Roots(p4,-5,5,out);
  3.     printf("\nOn affiche le signe de p4 sur [-5;5]\n" );
  4.     Sign(p4,-5,5);


Un peu de débugage :

Code :
  1. Breakpoint 1, Sign (p=0x0, x1=-5, x2=5) at aau.c:216
  2. 216  out2[N]=Roots(p,x1,x2,out2);
  3. (gdb) s
  4. Roots (p=0x0, x1=-5, x2=5, out=0xbfa46148) at aau.c:186
  5. 186  int n=0;
  6. (gdb)


 
Et là, j'ai les yeux embrouillés....


Message édité par 2xyo le 04-06-2008 à 23:33:54

---------------
2 * yo = yoyo
Reply

Marsh Posté le 05-06-2008 à 00:58:51    

Je lui ai pété un EPSILON dans la gueule   :love:


---------------
2 * yo = yoyo
Reply

Marsh Posté le 05-06-2008 à 01:44:18    

Youhou, ça marche... (Enfin pour une valeur précise d'EPSILON avec un polynome particulier...)

Reply

Marsh Posté le 05-06-2008 à 09:03:51    

montre le code de ton Allocate qu'on rigole ?

Reply

Marsh Posté le 05-06-2008 à 15:13:02    

Ce code est une horreur  :sweat: , ouvre un bouquin sur les bases du C (chapître tableau) ou (on peut réver) lis les réponses postées.
 

Code :
  1. #define N    100
  2. // .....
  3. return out[100];
  4. // .....
  5. double out[N];
  6. out[N]=Roots(p4,-5,5,out);


 
À la limite change au moins la déclaration de "out" en :
 

Code :
  1. double out[N + 1];


Reply

Marsh Posté le 05-06-2008 à 15:43:28    

Taz a écrit :

montre le code de ton Allocate qu'on rigole ?


Cette fonction vient de ce professeur http://perso.univ-rennes1.fr/jean-claude.nunes/

Code :
  1. struct Polynome *Allocate(unsigned int degre)
  2. {
  3.     struct Polynome *out;
  4.    
  5.     out = (struct Polynome *) malloc(sizeof(struct Polynome));
  6.     out->Degre = degre;
  7.     out->Coefficients = (double *) malloc((degre + 1) * sizeof(double));
  8.     return out;
  9. }


C'est si drôle que ça ? :o  
 

tpierron a écrit :

Ce code est une horreur  :sweat: , ouvre un bouquin sur les bases du C (chapître tableau) ou (on peut réver) lis les réponses postées.
 

Code :
  1. #define N    100
  2. // .....
  3. return out[100];
  4. // .....
  5. double out[N];
  6. out[N]=Roots(p4,-5,5,out);


 
À la limite change au moins la déclaration de "out" en :
 

Code :
  1. double out[N + 1];




Ce N+1 ne changerai rien. En effet, la fonction Roots était erroné et renvoyait plusieurs centaines de racines dans le tableau (avec N=10)...Il y avait juste un problème de calibration de la fonction Roots pour déterminer à partir de quand on détectait une racine assez proche de 0 pour être considérer égale à 0 (et par conséquent être enregistrer comme racine dans out[N]).  
 
Enfin, je ne voie pas trop l'intérêt de remarques comme ça "(on peut réver)"... (Tu as peut-être quelques connaissance en C mais cela ne te dispense pas d'un minimum de courtoisie)
 


---------------
2 * yo = yoyo
Reply

Marsh Posté le 05-06-2008 à 15:43:28   

Reply

Marsh Posté le 05-06-2008 à 16:04:22    

Petit test. Quoi que fasse la fonction Roots, ce code est foireux :
 

Code :
  1. double out[N];
  2. out[N]=Roots(p4,-5,5,out);


 
Tu n'as pas l'air de t'en rendre compte. On t'as donné la réponse, et t'as reposté un nouveau code avec la même annerie. Conclusion: tu ne lis pas les réponses ou tu ne les comprends pas, dans ce cas pose d'autres questions.

Reply

Marsh Posté le 06-06-2008 à 22:18:19    

tpierron a écrit :

Petit test. Quoi que fasse la fonction Roots, ce code est foireux :
 

Code :
  1. double out[N];
  2. out[N]=Roots(p4,-5,5,out);


 
Tu n'as pas l'air de t'en rendre compte. On t'as donné la réponse, et t'as reposté un nouveau code avec la même annerie. Conclusion: tu ne lis pas les réponses ou tu ne les comprends pas, dans ce cas pose d'autres questions.


 

Code :
  1. double out[N+1];
  2. uint racine;
  3. racine=Roots(p1,-1.0,3,out,0.1);


Autant pour moi. Le manque de sommeil, la mauvaise compréhension du prototype de Roots() et mes "connaissances" en C ne m'ont pas beaucoup aidé sur ce coup  :whistle: (Je ne poste pas pour le plaisir de poster, par conséquent, je regarde quand même les réponses)

Code :
  1. uint Roots(struct Polynome *p, double x1, double x2, double *out, double pas) /*On a modifier le protoype de Roots (cf compte rendu pour plus de détail) et ajouté un pas d'avancement*/
  2. {
  3.     uint n=0,j;                          /*Déclaration d'entier pour les boucles suivantes et le stockage du résultat */
  4.     double i;                           /*Réel pour l'avancement dans la boucle    */
  5.     for(j=0;j<N;j++)                              /*On parcour le tableau qui contiendra les racines */
  6.         out[j]=fabs(0.0);                            /*Et on l'initialise à 0.0       */
  7.     for(i=x1+pas;i<=x2;i+=pas)                               /*On "avance" sur la courbe de "pas"    */
  8.     {
  9.          if(fabs(Eval(p,i))<=EPSILON){                                     /*On calcul alors la valeur absolu et si elle est plus petite que notre marge d'erreur maximum EPSILON */
  10.      out[n]=i;                                /*Alors on considère que le polynome est égale à 0 et on enregistre dans le tableau la valeur de x   */
  11.      n++;                          /*On incrémente l'indice de la position du tableau des résultats          */
  12.  }
  13. }
  14.     return n;                          /*On retourne le nombre de racines     */
  15. }


 
P.S : L'indentation de ce forum est #@'é')'é  :kaola:


---------------
2 * yo = yoyo
Reply

Marsh Posté le 07-06-2008 à 15:03:29    

Code :
  1. struct Polynome *Allocate(unsigned int degre)
  2. {
  3.     struct Polynome *out;
  4.    
  5.     out = malloc(sizeof(struct Polynome));
  6.     out->Degre = degre;
  7.     out->Coefficients = (double *) malloc((degre + 1) * sizeof(double));
  8.     return out;
  9. }


Oui on peut rigoler effectivement :  
Une erreur : une précaution indispensable est de vérifier le retour du malloc, on ne sait jamais, le retour peut-être NULL auquel cas ton programme plante.
Une maladresse, mais là certains en discutent, en C, on ne caste pas en général le retour de malloc, il peut masquer l'oubli d'inclusion du .h déclarant la fonction malloc.
ton code corrigé pourrait donner ceci :

Code :
  1. struct Polynome *Allocate(unsigned int degre)
  2. {
  3.     struct Polynome *out;
  4.    
  5.     out = (struct Polynome *) malloc(sizeof(struct Polynome));
  6.     if (out != NULL)
  7.     {
  8.        out->Degre = degre;
  9.        out->Coefficients = malloc((degre + 1) * sizeof(double));
  10.        if (out->Coefficients == NULL)
  11.        {
  12.           // a toi de voir ce que tu veux faire
  13.        }
  14.     }
  15.     else
  16.     {
  17.        // a toi de vir ce que tu veux faire
  18.     }
  19.     return out;
  20. }


Message édité par Trap D le 07-06-2008 à 15:06:09
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed