Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1320 connectés 

  FORUM HardWare.fr
  Programmation
  C

  Allocation dynamique : question vague

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

Allocation dynamique : question vague

n°2146953
empereur d​'Esthar
Posté le 24-06-2012 à 20:15:09  profilanswer
 

Bonjour,
 
Je fais un peu de C à mes heures perdues et j'ai un bug qui revient souvent et auquel je ne comprends absolument rien.
Je n'ai malheureusement pas d'exemple pour le moment, ça apparait ou disparait de façon imprévisible (en tous cas pour moi c'est imprévisible  :pt1cable: ) quand je change des petites choses sans grand rapport dans mon code (mais si je le retrouve je poste le code, promis !)
 
Donc en fait ma question se résume à ça : A quoi peut être du un plantage lorsqu'on utilise free ?
J'ai d'abord pensé que free plantait lorsqu'on tentait de libérer un espace en mémoire qui n'est pas alloué au programme, j'ai donc testé le pointeur que je voulais free (ça peut être tout et n'importe quoi, j'ai eu ce problème avec des chaines de caractères, avec des listes chainées, ...) de la façon suivante : déjà j'ai vérifié que sa valeur ne changeait pas entre le malloc et le free, ensuite j'ai modifié la variable pointée juste avant de la free (dans la même fonction, vraiment juste avant !), le dernier caractère d'une chaine par exemple ou encore tous les éléments d'une structure, pour vérifier que cet espace en mémoire appartient bien à mon programme, jusque là aucun bug, et quand on arrive à free => "test.exe a cessé de fonctionner".
 
Grossièrement j'aimerais déjà savoir si ce type de bug est connu, sinon dès que je tombe dessus et que j'ai un exemple qui me le fait, je le poste.
Merci par avance de l'aide que vous pourrez m'apporter  :jap:  
 
Des fois que ça soit utile à savoir : je code avec code::blocks 10.05, sous windows 7.

mood
Publicité
Posté le 24-06-2012 à 20:15:09  profilanswer
 

n°2146955
xilebo
noone
Posté le 24-06-2012 à 20:28:32  profilanswer
 

un exemple de code qui peut planter :
 

Code :
  1. #include <stdlib.h>
  2. int main()
  3. {
  4. char * toto = malloc ( 10 );
  5. free ( toto );
  6. free ( toto );
  7. return 0;
  8. }


 
( pointeur déjà libéré ).
 
Tu peux également avoir un écrasement mémoire dans la zone qu'utilise malloc pour gérer la liste des segments alloués. Et là , comportement indéterminé, donc probablement plantage ( au moment où free parcours la liste chaînée pour trouver l'élément à libérer ).

n°2146956
Terminapor
I'll see you rise.
Posté le 24-06-2012 à 20:29:24  profilanswer
 

Ben, sans code c'est difficile à dire.
Sinon, oui un free sur une adresse inexistance / déjà supprimé ça fait planté le programme (segmentation fault), t'as pas un debugger sous la main histoire d'avoir le nom du signal d'arrêt ?


---------------
Perhaps you don't deserve to breathe
n°2146973
Sve@r
Posté le 24-06-2012 à 22:09:42  profilanswer
 

empereur d'Esthar a écrit :

ça apparait ou disparait de façon imprévisible (en tous cas pour moi c'est imprévisible  :pt1cable: ) quand je change des petites choses sans grand rapport dans mon code
Salut


Tu décris ici une situation caractéristique d'un "comportement indéterminé".
Un comportement indéterminé se produit quand on fait faire au C une action qui n'est pas prévue par la norme. Ca peut-être (en vrac) aller lire une zone mémoire non allouée, lire un membre d'une union qui n'est pas le membre qui a été rempli, regarder la valeur d'une adresse qui ne t'appartient pas , etc etc.
Et donc le comportement indéterminé se traduit exactement comme son nom l'indique => il est impossible de prévoir le comportement du programme. Le programme peut fonctionner, il peut planter, il peut fonctionner le lundi et planter le mardi, il peut fonctionner plusieurs mois ou plusieurs années jusqu'à ce que tu le modifies de façon totalement mineure (comme rajouter un simple printf()). Bref c'est le pire des cas. On a vu un lanceur Ariane se crasher parce que le calculateur avait été testé dans l'hémisphère nord et quand on est passé dans l'hémisphère sud, le sinus est passé en négatif et le cas n'avait pas été prévu (enfin c'est une histoire que nous a raconté notre prof de maths mais je ne l'ai pas vérifiée)
 

empereur d'Esthar a écrit :

Donc en fait ma question se résume à ça : A quoi peut être du un plantage lorsqu'on utilise free ?


Généralement tu libères une zone non allouée ou déjà libérée.
 

empereur d'Esthar a écrit :

...ou encore tous les éléments d'une structure, pour vérifier que cet espace en mémoire appartient bien à mon programme


Ca ne veut rien dire. free() indique au système que la zone est libre mais ne la vide pas (pourquoi faire d'ailleurs puisqu'elle sera remplie quand ce sera nécessaire). Donc tu peux libérer ta zone, le contenu n'a pas changé. Mais il n'est plus à toi.
 
Pour éviter ce bug, 2 solutions
1) tu maitrises tes pointeurs à la perfection. Tu alloues quand il faut, tu sais en permanence quand c'est alloué et tu libères quand il faut. C'est la meilleure solution mais pas la plus facile
2) tu remplis systématiquement chaque pointeur libéré par NULL. En effet, free() détecte si le pointeur passé est à NULL et si c'est le cas, ne fait rien.

Code :
  1. char*c;
  2. ...
  3. c=malloc(...);
  4. ...
  5. free(c), c=NULL;


Ainsi si free() est de nouveau invoqué par erreur

Code :
  1. free(c), c=NULL;
  2. ...
  3. free(c), c=NULL;


Le second appel à free() sera ignoré.
C'est la solution de facilité parce qu'appeler free une fois de trop reste quand-même une action inutile et a donc l'inconvénient irréparable de ralentir inutilement ton code...
 

empereur d'Esthar a écrit :

Des fois que ça soit utile à savoir : je code avec code::blocks 10.05, sous windows 7.


Peut-être aussi que code::blocks est buggué (hypothèse qu'on ne peut pas écarter)...

n°2146976
Terminapor
I'll see you rise.
Posté le 24-06-2012 à 22:20:52  profilanswer
 

Ouais, euh, Code::block n'est qu'un IDE hein :o


---------------
Perhaps you don't deserve to breathe
n°2147223
empereur d​'Esthar
Posté le 26-06-2012 à 18:42:58  profilanswer
 

Citation :

On a vu un lanceur Ariane se crasher parce que le calculateur avait été testé dans l'hémisphère nord et quand on est passé dans l'hémisphère sud, le sinus est passé en négatif et le cas n'avait pas été prévu (enfin c'est une histoire que nous a raconté notre prof de maths mais je ne l'ai pas vérifiée)


 
J'ai du mal à y croire mais c'est amusant comme histoire ^^
 
Je me suis rendu compte hier qu'il m'était arrivé plusieurs fois de faire des mallocs avec un type de la forme "type*" au lieu de "type" (probablement du la prise d'une substance illicite avant de coder ...), j'ai pas encore vérifié dans mes autres projets si c'était la même connerie que j'avais faite mais en tous cas je re-regarderais à la lumière de ce que vous m'avez dit ici, merci :)

n°2147230
tpierron
Posté le 26-06-2012 à 19:56:19  profilanswer
 

Pour m'en être bouffé une tétrachiée d'erreur de ce type, je peux t'assurer que ce genre d'erreur resemble plus à un buffer overflow, qu'à une double libération d'un bloc mémoire. Il ne suffit de pas grand chose en fait: écrire un octet avant ou après le bloc = plantage quasi assuré au prochain malloc/free. D'autant plus la merde que l'endroit où ça va planter, ne sera pas l'endroit où le buffer overflow a eu lieu.

 

Le seul moyen vraiment sûr pour détecter ce genre d'erreur, c'est d'utiliser des outils type valgrind (ça excécute ton programme dans une machine virtuelle où tous les accès mémoires sont vérifiés). Il n'est malheureusement dispo que sous Linux, sous Windows il n'y a que des outils proprio (j'avais un jour testé purify: bah, ça vaut pas valgrind).


Message édité par tpierron le 26-06-2012 à 19:56:42
n°2147233
xilebo
noone
Posté le 26-06-2012 à 20:17:12  profilanswer
 

boundschecker est pas mal, cher mais une version d'évaluation est possible.

n°2147608
empereur d​'Esthar
Posté le 29-06-2012 à 21:11:09  profilanswer
 

En effet c'est traitre comme erreur, ce pourquoi je vérifie ça assez rapidement. Cela dit ces outils paraissent intéressants, j'y penserais si un jour je suis à la limite de passer l'ordi par la fenêtre ^^

n°2147626
bjone
Insert booze to continue
Posté le 30-06-2012 à 11:08:09  profilanswer
 

Sve@r a écrit :


On a vu un lanceur Ariane se crasher parce que le calculateur avait été testé dans l'hémisphère nord et quand on est passé dans l'hémisphère sud, le sinus est passé en négatif et le cas n'avait pas été prévu (enfin c'est une histoire que nous a raconté notre prof de maths mais je ne l'ai pas vérifiée)


 
Heu non, la première "auto-destruction" d'Ariane 5 était dû à un bout de code (écrit en Ada) réutilisé d'Ariane 4 qui a déclenché une exception lors d'une conversion d'un flottant 64bits en entier 16bits. Sur un bout de code qui n'était utile qu'à la calibration au sol et qui n'avait plus de pertinence une fois le décollage lancé.
http://www.astrosurf.com/luxorion/ [...] e-v501.htm

mood
Publicité
Posté le 30-06-2012 à 11:08:09  profilanswer
 

n°2147675
theshockwa​ve
I work at a firm named Koslow
Posté le 01-07-2012 à 15:47:23  profilanswer
 

si tu utilises visual, tu peux faire des appels à _CrtCheckMemory à des points clés, ca peut être assez utile et ca détecte très bien les dépassement de capacités.


---------------
last.fm
n°2150806
edwoud
⭐ shériff de l'espace
Posté le 25-07-2012 à 09:52:49  profilanswer
 


Il existe des tonnes d'outils pour détecter ce genre de choses dont le plus connu est Valgrind -> http://valgrind.org/
 
Perso, ça fait des années que je me suis fait mon propre wrapper mémoire.
 
Ainsi, en développement et debug, tous mes appels sont détournés et si je veux libérer deux fois, même si je déborde un peu en écrivant, ma librairie me donnera le source, la fonction et la ligne de code qui pose problème.
 
En production, tous est désactivé et le programme peut tourner à fond les ballons

n°2150851
theshockwa​ve
I work at a firm named Koslow
Posté le 25-07-2012 à 11:09:25  profilanswer
 

Avoir sa propre bibliothèque pour gérer les allocations est une bonne chose, c'est certain .. Mais quand il est question de quelqu'un qui a du mal avec les concepts même d'allocation et les opérateurs ou fonctions à utiliser, c'est compliqué de lui recommander de se faire sa propre bibliothèque.


---------------
last.fm
n°2150933
edwoud
⭐ shériff de l'espace
Posté le 25-07-2012 à 14:20:20  profilanswer
 

theshockwave a écrit :

Avoir sa propre bibliothèque pour gérer les allocations est une bonne chose, c'est certain .. Mais quand il est question de quelqu'un qui a du mal avec les concepts même d'allocation et les opérateurs ou fonctions à utiliser, c'est compliqué de lui recommander de se faire sa propre bibliothèque.


 
Sauf que je lui recommande Valgrind  :D  
 
Si il veut aller plus loin, il pourra se faire sa bibliothèque, mais c'est pour aller plus loin ça  :jap:


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C

  Allocation dynamique : question vague

 

Sujets relatifs
Recherche Excel / Dernier événementmacro Excel pour un graphique dynamique
Comment compter le nombre de lignes dans un tableau croisé dynamique ?[vbs] nom de variable dynamique
Question sur un script qui ajoute un profil OutlookPetite question PHP, noob :)
Macro tableau croisé dynamique[jquery] Question un peu bateau sur les boucles
Question sur lecture fichierAllocation fichier en entrée / sortie
Plus de sujets relatifs à : Allocation dynamique : question vague


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR