STL et std::bad_alloc en mode release

Signaler
Messages postés
185
Date d'inscription
samedi 21 mai 2005
Statut
Membre
Dernière intervention
16 juillet 2016
-
Messages postés
185
Date d'inscription
samedi 21 mai 2005
Statut
Membre
Dernière intervention
16 juillet 2016
-
Bonjour,

Je me heurte à un gros problème depuis quelques mois et, travaillant principalement en debug, je ne m'y était pas attardé mais celui-ci m'inquiétait tout de même pour le déploiement. Je suis sous Visual Studio C++ Express 2005, j'utilise l'API win 32 de base le sous système window, bref un projet Win32 graphique de base sans MFC ou toutes ces cochonneries.cela fait un an que je programme en C++/Qt/minGW et j'avoue que je ça me suffit parce que c'est génial, mais je suis, pour une seule application de mon projet, obligé de passer par Visual Studio.
Mon gros problème c'est que mon programme compile et fonctionne en Debug avec génération des informations de débugage et utilisation des DLL de débugage multithread (/MTd) exclusivement et compile en mode release, mais là ça plante à l'éxécution. J'ai donc rajouté l'option de génération des infos de débugage et il se trouve que ce sont les création d'objets de la STL map, string, sstream, vector et autres en allocation statique qui me font planter mon appli (std::bad_alloc ...).
J'ai cherché un peu et je suis tombé sur cet article là :
MSDN STL bad::alloc
Et là ça me fout une grosse claque. Mon projet VC++ commence à être conséquent et venant de la librairie "Framework" Qt avec qui tout est facile et déjà inventé, tout mon projet VC++ est basé sur l'utilisation des STL parce qu'à un moment faut arrêter de réinventer la roue... Et là, ça grosso modo l'article dit que la STL en projet VC++ sans MFC, sans .NET, un projet de base, l'opérateur new causerait des erreurs d'allocation mémoire en mode release. C'est hallucinant tout de même, je tombe vraiment de haut, même les truc légèrement évolués ne fonctionnent qu'à moitié sous windows...
J'ai pas très bien compris ce qu'il fallait faire pour éviter ça, l'article donne des solution suivant le type de projet utilisé, mais n'y a-t-il vraiment pas d'autre solution, c'est un problème aberrant auquel il doit bien y avoir une autre solution que de surcharger l'opérateur new tout de même ???? non ? genre mise à jour de librairie ou un truc comme ça
Moi je dis vive Qt, au moins ça ne fait pas semblant de simplifier la vie...
Je sais qu'il y a boost aussi, mais les types et l'utilisation des string, map et autres doivent être différent et ça m'embête de devoir remanier tout mon projet... si tant est qu'il n'y a pas le même problème
Une solution ???

Merci

Hervé

L'intelligence est la chose la mieux répartie chez l'homme, car quoi qu'il en soit pourvu, il a toujours l'impression d'en avoir assez. "Descartes"

5 réponses

Messages postés
185
Date d'inscription
samedi 21 mai 2005
Statut
Membre
Dernière intervention
16 juillet 2016

En fait, je crée dans une classe
class MyClass{
    MyClass()
   {
      something or not...
   }
    map<string,int> myMap;
}


en mode release mais en générant les information de débugage afin d'utiliser les points d'arrêt, je n'atteins même pas le corps du constructeur, c'est bien que l'erreur se situe à la création même de l'instance de MyClass. Il se trouve que lorsque je supprime myMap et tout ce qui est STL, j'atteins enfin le corps du constructeur, cela prouve bien que c'est la création de ma std::map qui fait planter le truc.
Je précise cela car dans l'article cité ci-dessus, il parle de l'opérateur new, opérateur que je n'utilise pas explicitement puisque je crée myMap en statique mais la STL l'utilise sans aucun doute pour gérer dynamiquement la taille de myMap, avant même que j'y ajoute quelque chose.
Pouvez-vous bien me confirmer que c'est le même problème ? car comme je ne l'appelle pas explicitement et ne souhaite pas le faire puisque ça complique la syntaxe, je ne vois pas comment pourquoi j'aurai à surcharger l'opérateur new.
Boost est-elle une lib qui se base sur la STL ? car dans ce cas je crains de finir par avoir le même genre de problème...

Merci

L'intelligence est la chose la mieux répartie chez l'homme, car quoi qu'il en soit pourvu, il a toujours l'impression d'en avoir assez. "Descartes"
Messages postés
3874
Date d'inscription
mardi 8 mars 2005
Statut
Modérateur
Dernière intervention
7 novembre 2014
13
Salut,

If you are one of them and are using STL and Visual C++ 6.0 directly out of the box, your application is at high risk of crashing under low memory conditions.
De ce que je l'ai parcourut, l'article explique surtout que Visual Studio 6 renvoyait NULL lors de l'échec d'une allocation, alors que les versions ultérieures déclenchent une exception, comme la norme le stipule.

Quoiqu'il en soit, les problèmes surviennent lorsqu'une allocation échoue.

Et ça, en natif sous Windows, c'est extrêmement rare. Il faut vraiment pousser le PC dans ses retranchements.

Autrement dit, il y a un problème dans ton code ou dans la STL. Mais sachant que la STL est utilisée intensivement, et est de bien meilleur qualité sous 2005 que sous VC6, il est plus probable qu'il se situe dans ton code.

Globalement, pour qu'une allocation échoue, il y a deux causes :
1) Le système d'exploitation ne peut plus trouver de mémoire.
2) La taille de mémoire contigüe demandée est trop grande.
3) Le tas est en vrac.

Le premier cas se voit rapidement. Le PC est à genou : ralentissement, saccades, peu de réactivité... La mémoire consommée visible dans le gestionnaire des tâches est largement supérieure à la quantité de RAM disponible (Parfois 3 ou 4 fois plus de mémoire consommée que de RAM). La mémoire virtuelle est pleine elle aussi et Windows tente désespérément d'augmenter sa taille. Pour que ce problème survienne, il faut qu'il y ait une grande quantité d'allocations de bonne taille. Cela peut avoir lieu en cas de récursivité. Par exemple, si une string à besoin d'une string pour être construite, on va bouffer toute la mémoire. Cela peut bien sûr aussi avoir lieu si le logiciel manipule une grande quantité de données, ou en cas de fuite de mémoire.

Le deuxième cas peut survenir alors que le PC est moins chargé. Si on demande 4Go de mémoire contigüe, on les a pas, c'est tout, peu importe la charge. Cela signifie que d'une manière ou d'une autre : Allocation d'une matrice 1000000 * 1000 entiers, écrasement mémoire provoquant une demande de mémoire de taille erronée, calcul de taille mal codé (genre int i; int* titi = new int[i]; sans i initialisé)...

Le troisième cas, c'est quand on a cassé le tas. On a écrit là où le gestionnaire de tas du C++ a écrit des infos sur son tas. Bilan il ne s'y retrouve plus. Ca arrive quand on écrit à côté de zones allouées, par exemple en dépassant les bornes d'un tableau.

Bilan, il faut que tu regardes l'état de la mémoire de ton PC. S'il n'y a rien de suspect, il faut que tu fasses des investigations pour déterminer quelle allocation déclenche l'exception, ou s'il y en a plusieurs.
Messages postés
202
Date d'inscription
dimanche 18 mai 2003
Statut
Membre
Dernière intervention
6 mars 2010

std::map et la STL en général marche très bien, des milliers de gens l'utilisent tous les jours, il y a pas de soucis à ce faire de ce coté la.

maintenant pour ton problème, je penche plutôt pour une corrumption du tas (vérifie comme même que ton process ne bouffe pas 2 Go ). tu peux checker en debug l'intégrité du tas pas la fonction "_CrtCheckMemory" ou bien par la fonction "_CrtSetDbgFlag" qui permet de vérifier ton tas toutes les X allocations.
Messages postés
202
Date d'inscription
dimanche 18 mai 2003
Statut
Membre
Dernière intervention
6 mars 2010

ah, j'ai oublié un peu de doc pour ces fonctions : ici
Messages postés
185
Date d'inscription
samedi 21 mai 2005
Statut
Membre
Dernière intervention
16 juillet 2016

Merci,

Je penche aussi pour un problème de new et/ou delete quelque part, mais j'en fait tellement peu, grâce à l'utilisation de la STL justement, que c'est vraiment pas de bol. Merci en tout cas pour ces infos et explications

L'intelligence est la chose la mieux répartie chez l'homme, car quoi qu'il en soit pourvu, il a toujours l'impression d'en avoir assez. "Descartes"