2010-07-14 4 views
0

Я столкнулся с ситуацией (на Win32), где объект std :: ostringstream продолжает потреблять память процесса, даже если это якобы очищается после серии операций типа append. Пожалуйста, обратите внимание на этот фрагмент C++:C++ STL в VS2008: std :: ostringstream throws std :: bad_alloc после тяжелого присвоения/явного использования

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); 
    } 
} 

Во время выполнения внутренней, а() цикл, наблюдение за использованием памяти текущего процесса в диспетчере задач показывает непрерывный восходящий пандус, который в конечном итоге уровень выключения. Однако это выравнивание происходит одновременно с ошибкой std :: bad_alloc. Это предполагает, что память кучи либо исчерпана, либо запрошенный размер блока недоступен в непрерывном пространстве.

Кто-нибудь еще испытал это ядовитое явление с объектами ostringstream и какие другие альтернативные объекты доступны вместо этого сломанного?

Большое спасибо!

ответ

2

Я не вижу, как этот код может воспроизвести проблему. После того, как шаг петлителя увеличивается до 45, он должен быть занят потреблением любой памяти.

Общая диагностика заключается в том, что программе очень редко удается использовать всю возможную доступную виртуальную память. Сначала он умрет, найдя кусок смежных байтов внутри кучи, достаточно большой для хранения буфера строкового потока. Это называется фрагментацией адресного пространства, вы ничего не можете с этим поделать. Ваш вызов Sleep(), безусловно, ничего не поможет, для консолидации выделенных блоков кучи требуется сборщик мусора.

Еще одна довольно стандартная ловушка использует TaskMgr.exe для диагностики использования памяти. Он обычно отображает рабочий набор, объем виртуальной памяти, отображаемый в ОЗУ. Это, как правило, лишь часть объема виртуальной памяти, потребляемой вашей программой, и не может дать реальную оценку того, сколько виртуальной памяти потребляет ваша программа. Или скажите вам что-нибудь о фрагментации адресного пространства, если на то пошло.

Утилита VMMap SysInternals может показать вам, как ваша программа использует виртуальную память.