[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: Un bug dans la STL ?



Le Wed, Apr 27, 2005 at 07:09:34PM +0200, Pierre THIERRY écrivait/wrote:
> Hello,
> 
> je suis en train de me mettre à écrire une bibliothèques de classes en
> C++, qui me servira ensuite pour des logiciels de jeu (principalement du
> jeu de rôle).
> 
> Je commence par les dés, et je suis tombé sur un os : une de mes
> classes comprend un méthode qui est censée désallouer des objets dont
> les pointeurs sont stockés dans un conteneur de la STL, qui est un
> membre privé de la classe, et vider celui-ci au passage.
> 
> Avec trois types différents, j'obtiens trois bugs différents, l'un très
> grave.
> 
> Si c'est un vector<MonType*>, impossible de vider. un pop_back() quand
> size() renvoit 1 fait passer à un état où size() renvoit 33635908
> (2^25+81476, je trouvais que c'est étrangement « proche » d'une
> puissance de 2),
> 
> Si c'est un deque<MonType*>, au bout de quelques secondes, la machine
> plante lamentablement, impossible de passer sur une console texte ou de
> tuer le serveur X. Seule possibilité, les Magic Keys du kernel, SIUB. Et
> lorsque la machine redémarre, kernel panic. Un redémarrage
> supplémentaire et elle démarre comme une fleur.
> 

J'imagine qu'il y a une fuite mémoire, c'est à dire que vous utilisez
la STL (que je connais mal) en C++ (que je n'aime guère) de façon à
utiliser toute la mémoire disponible. Je n'ai pas le temps de plonger
dans votre code. Mais si vous utilisez toute la mémoire (surtout en
overcommit) vous pouvez observer un plantage sevère.

Pour éviter de planter la machine (et pour trouver plus rapidement vos
bogues) une solution serait de limiter l'espace mémoire disponible
pour votre processus. L'appel système correspondant est setrlimit avec
RLIMIT_AS ou RLIMIT_DATA, et votre shell l'interface par le builtin
ulimit -v (pour bash) ou limit datasize (pour zsh et csh); aussi le
plus simple est de taper la commande 'limit datasize 50m" dans le
terminal zsh que vous utilisez pour tester votre programme.

Pour ma part, je prefère les langages dont l'implementation a un bon
ramasse-miettes (ou GC= glaneur de cellules = garbage
collector). Essayez par exemple Ocaml (http://caml.inria.fr/) à ce
sujet. En efet, un ramasse-miettes vous facilite la vie, car vous
n'avez plus à libérer explicitement vos données (mais vous pouvez
quand même déborder votre mémoire avec des données "vivantes" qui
croissent indéfiniement). Ne jugez pas les ramasses-miettes à l'aune
de Java.  Il existe aussi plusieurs ramasses-miettes utilisables en C
ou en C++; le plus connu est celui de Boehm: qui étant conservatif est
simple à utiliser - remplacer new par new(GC) par exemple, ou malloc
par GC_malloc; mais ce GC peut fuire un peu; il y a aussi Qish
http://starynkevitch.net/Basile/qishintro.html qui est un GC exact qui
nécessite des règles de codage très stricts et contraignantes et n'est
pas multi-threadé. Le dernier "snapshot" de Qish est disponible en
http://starynkevitch.net/Basile/qish-snapshot.tar.gz et son md5sum est
bcfd620283e2c6d083d7fd379bd3cc75

Bon courage, en espérant vous avoir un petit peu aidé.

-- 
Basile STARYNKEVITCH         http://starynkevitch.net/Basile/ 
email: basile<at>starynkevitch<dot>net 
aliases: basile<at>tunes<dot>org = bstarynk<at>nerim<dot>net
8, rue de la Faïencerie, 92340 Bourg La Reine, France



Reply to: