2010-07-14 16 views
0

Je suis tombé sur une situation (sur Win32) où l'objet std :: ostringstream continue de consommer de la mémoire de processus, même quand il est ostensiblement effacé après une série d'opérations append-type. S'il vous plaît jeter un coup d'oeil à ce C++ fragment:C++ STL dans VS2008: std :: ostringstream lance std :: bad_alloc après un usage lourd assign/clear

int main(void) 
{ 
    std::ostringstream cOutputLogStream; 

    // Random long string 
    std::string sTest = "jkspoiauyeraspfoiusdfsdfekgpweojkgpwoekpokgkpgeopoegwj"; 

    std::string sEmpty = ""; 

    int n = 0; 
    int looper = 0; 

    while (n++ < 100000) 
    { 
     while (looper++ < 45) 
     { 
      cOutputLogStream << s; 
     } 

     cOutputLogStream.str(sEmpty); 
     cOutputLogStream.clear(); 

     // This should give the heap manager a chance to consolidate 
     // fragmented memory blocks 
     Sleep(1); 
    } 
} 

Pendant l'exécution du temps interne() boucle, l'observation de l'utilisation de la mémoire du processus dans le gestionnaire de tâches montre une rampe ascendante continue, qui finit par se stabilise. Cependant, cette mise à niveau se produit en même temps que lorsque l'erreur std :: bad_alloc est renvoyée à plusieurs reprises. Cela suggère que la mémoire de segment a été épuisée ou que la taille de bloc demandée n'est pas disponible dans un espace contigu. Est-ce que quelqu'un d'autre a expérimenté ce phénomène de fuite avec des objets ostringstream, et quels autres objets alternatifs sont disponibles à la place de ce flaky?

Merci beaucoup!

Répondre

2

Je ne vois pas comment ce code pourrait reprocher le problème. Après l'incrément de looper à 45, il devrait être sur le point de consommer de la mémoire.

Le diagnostic générique est qu'un programme parvient très rarement à consommer toute la mémoire virtuelle disponible. Il mourra d'abord en trouvant un morceau d'octets contigus à l'intérieur du tas qui est assez grand pour stocker le tampon de flux de chaîne. C'est ce qu'on appelle la fragmentation de l'espace d'adresse, il n'y a rien que vous puissiez faire à ce sujet. Votre appel Sleep() ne fera certainement rien d'utile, la consolidation des blocs de tas alloués nécessite un garbage collector.

Un autre piège assez standard utilise TaskMgr.exe pour diagnostiquer l'utilisation de la mémoire. Il affiche normalement l'ensemble de travail, la quantité de mémoire virtuelle mappée à la RAM. Cela ne représente généralement qu'une fraction de la quantité de mémoire virtuelle consommée par votre programme et ne peut pas donner une mesure réelle de la quantité de mémoire virtuelle consommée par votre programme. Ou vous dire quelque chose sur la fragmentation de l'espace d'adresse d'ailleurs.

L'utilitaire VMMap de SysInternals peut vous montrer comment votre programme utilise la mémoire virtuelle.