C ++ STL в VS2008: std :: ostringstream выбрасывает std :: bad_alloc после интенсивного использования назначения / очистки - PullRequest
0 голосов
/ 14 июля 2010

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

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

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

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

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

1 Ответ

2 голосов
/ 14 июля 2010

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

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

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

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

...