GNT sans publicité, site mobile, fonctionnalitées exclusives...

[C/Unix] Problème de copie à l'écriture avec fork()

Le
JKB
Bonjour à tous,

Je butte sur un problème qui doit être idiot. J'ai un programme
écrit en C sous Unix qui a une fuite de mémoire assez conséquente
lors d'un fork (ça peut faire quelques Mo).

Considérons une processus père qui effectue une boucle. Dans cette
boucle, il fait un fork() et continue ses traitements dans lesquels
il y a des allocations de gros blocs de mémoire.

Le fils est fichu de voir ces allocations alors qu'elles ont lieu
_après_ le fork().

Grossièrement, l'algorithme est le suivant :

while(1)
{
ios = fork();

if (ios = 0)
{
// plein de trucs tordus
exit(0);
}
else
{
// sleep();
mem = malloc();
// plein de trucs abscons
free(mem);
}
}

et je récupère le pointeur mem dans le processus fils ! Je ne vois
qu'une seule explication, le fork() en question est une copie à
l'écriture pour le fils et se fait entre le malloc() et le free().
Ou alors, le free() est reporté à plus tard et s'exécute en tâche de
fond lors de l'appel à fork(). Il faut noter que je ne
récupère ce pointeur qu'après quelques itérations. Je suis incapable
de le recevoir lors de la première, mais je ne sais pas si c'est
significatif.

Le père n'a _aucune_ fuite de mémoire (testé dans tous les sens avec
valgrind et des outils fait maison). La fuite n'apparaît que dans
les fils.

Si je rajoute un sleep() pour bloquer le père durant quelques
dixièmes de secondes, la fuite de mémoire disparaît dans les fils.
Il y a un thread parallèle au père mais il ne fait strictement
aucune allocation et j'ai testé avec hellgrind qui ne m'a trouvé
aucune race condition.

Est-ce que l'un d'entre vous aurait une idée pour forcer la copie
dès le fork() et éliminer ce problème ? Je ne suis pas sûr que ça
vienne de là, mais je préfère ôter ce doute avant de chercher
ailleurs.

Cordialement,

JKB

--
Le cerveau, c'est un véritable scandale écologique. Il représente 2% de notre
masse corporelle, mais disperse à lui seul 25% de l'énergie que nous
consommons tous les jours.
=> http://grincheux.de-charybde-en-scylla.fr
Lire les 13 réponses

Vidéos High-Tech et Jeu Vidéo
Téléchargements
Vos réponses Page 1 / 3
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
espie
Le #22267901
In article JKB
while(1)
{
ios = fork();

if (ios = 0)


^
Bon, je sais que c'est un exemple, mais j'espere que tu n'as pas la meme
faute stupide dans le programme lui-meme...
JKB
Le #22267891
Le 17-06-2010, ? propos de
Re: [C/Unix] Problème de copie à l'écriture avec fork(),
Marc Espie ?crivait dans fr.comp.lang.c :
In article JKB
while(1)
{
ios = fork();

if (ios = 0)


^
Bon, je sais que c'est un exemple, mais j'espere que tu n'as pas la meme
faute stupide dans le programme lui-meme...



Non, c'est un simple exemple que je n'ai même pas compilé parce que
le programme en lui-même est _beaucoup_ plus long.

JKB

--
Le cerveau, c'est un véritable scandale écologique. Il représente 2% de notre
masse corporelle, mais disperse à lui seul 25% de l'énergie que nous
consommons tous les jours.
=> http://grincheux.de-charybde-en-scylla.fr
Marc Boyer
Le #22268081
Le 17-06-2010, JKB
Bonjour à tous,

Je butte sur un problème qui doit être idiot. J'ai un programme
écrit en C sous Unix qui a une fuite de mémoire assez conséquente
lors d'un fork (ça peut faire quelques Mo).



Et ça dure combien de temps ?
free est asynchrone en général. Est-ce que ça ne vient pas
simplement du fait que chaque fils ne vis pas assez longtemps pour
que l'OS décide de libérer vraiment la mémoire ?

et je récupère le pointeur mem dans le processus fils !



Que veux-tu dire ? Il est normal, dès la deuxième itération de
la boucle, que les fils voient mem != NULL.

Marc Boyer
--
En prenant aux 10% des francais les plus riches 12% de leurs revenus,
on pourrait doubler les revenus des 10% les plus pauvres.
http://www.inegalites.fr/spip.php?a...amp;id_mot0
JKB
Le #22268071
Le 17-06-2010, ? propos de
Re: [C/Unix] Problème de copie à l'écriture avec fork(),
Marc Boyer ?crivait dans fr.comp.lang.c :
Le 17-06-2010, JKB
Bonjour à tous,

Je butte sur un problème qui doit être idiot. J'ai un programme
écrit en C sous Unix qui a une fuite de mémoire assez conséquente
lors d'un fork (ça peut faire quelques Mo).



Et ça dure combien de temps ?



Je ne saisis pas la question.

free est asynchrone en général. Est-ce que ça ne vient pas
simplement du fait que chaque fils ne vis pas assez longtemps pour
que l'OS décide de libérer vraiment la mémoire ?



Si je colle un sleep dans le fils, le résultat est identique.

et je récupère le pointeur mem dans le processus fils !



Que veux-tu dire ? Il est normal, dès la deuxième itération de
la boucle, que les fils voient mem != NULL.



Abus de langage : je récupère un pointeur valide (sur lequel je peux
faire un free() sans que valgrind ne râle).

JKB

--
Le cerveau, c'est un véritable scandale écologique. Il représente 2% de notre
masse corporelle, mais disperse à lui seul 25% de l'énergie que nous
consommons tous les jours.
=> http://grincheux.de-charybde-en-scylla.fr
Dominique MICOLLET
Le #22268251
JKB wrote:

Un problème de fuite



Il semble que mem soit déclaré en dehors de la boucle while : il est donc
normal que le second fork et ses suivants voient dans mem une valeur qui a
pointé à une époque sur un bloc alloué et qui ne devrait plus l'être.



Par contre je ne comprends pas qu'il y ait une fuite mémoire dans ce cas,
puisque les deux processus devraient travailler dans des zones mémoires
différentes.


Ceci étant dit, le man de fork sous linux dit qu'il travaille en copy on
write : je ne suis pas très sûr de ce que ça implique mais il se pourrait
bien que mem ne soit pas véritablement dupliqué.... Dans cette même doc, il
est écrit que fork est en fait réalisé à partir de clone, qui sert
normalement à faire du multiflots, pour lequel l'espace est partagé.
Donc ce que vous constatez est peut-être "normal" au vu de l'implémentation.

Compte tenu des allocations/desallocations, essayez de déclarer mem dans le
bloc else du processus parent, ou forcez le à NULL après la désallocation.
Essayez aussi éventuellement de forcer mem à NULL (voire n'importe quoi)
dans le processus fils : si j'ai bien compris le concept de copy-on-write,
les fuites devraient disparaître.

Précisez éventuellement la plateforme sur la laquelle vous travaillez.

Cordialement.
--
Dominique MICOLLET
Adresse email : enlever deux francs
Publicité
Suivre les réponses
Poster une réponse
Anonyme