Realloc() неправильно освобождает память в Windows

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

Я обнаружил, что хотя realloc() работает правильно (память в диспетчере задач отражает то, что вы ожидаете), приложение в конечном итоге исчерпывает память. Насколько я могу судить, похоже, что relloc() освобождает память, но не освобождает виртуальное адресное пространство, связанное с памятью. В результате malloc() в конечном итоге завершится неудачей.

Вот небольшое консольное приложение, которое демонстрирует эту проблему:

int _tmain(int argc, _TCHAR* argv[])
{
    static const DWORD dwAllocSize = (50 * 1024 * 1024);
    static const DWORD dwReallocSize = 10240;
    static const DWORD dwMaxIterations = 200;

    BYTE* arpMemory[dwMaxIterations];
    memset( arpMemory, 0, sizeof(arpMemory) );

    for( DWORD i = 0; i < dwMaxIterations; i++ )
    {
        arpMemory[i] = (BYTE*) malloc( dwAllocSize );
        if( !arpMemory[i] )
        {
            printf("OUT OF MEMORY after %d iterations!\n", i);
            return -1;
        }

        BYTE* pRealloc = (BYTE*) realloc( arpMemory[i], dwReallocSize );
        if( !pRealloc )
        {
            printf("Realloc FAILED after %d iterations!\n", i);
            return -1;
        }
        else if( pRealloc != arpMemory[i] )
        {
            printf("Warning: Pointer changed: 0x%08X -> 0x%08X\n", arpMemory[i], pRealloc);
            arpMemory[i] = pRealloc;
        }
    }

    printf("Success!\n");

    for( int i = 0; i < dwMaxIterations; i++ )
        free( arpMemory[i] );

    return 0;
}

Приложение многократно выделяет 50 МБ памяти, а затем сразу же изменяет ее размер до 10К. Если вы запустите его, то обнаружите, что оно завершается с ошибкой OUT OF MEMORY только после 38 итераций. Это соответствует 2 ГБ первоначально выделенной памяти - что является ограничением адресного пространства для приложений Windows.

Интересно, что если вы посмотрите в диспетчере задач, то увидите, что приложение практически не занимает памяти. Тем не менее malloc() не работает. Это наводит меня на мысль, что виртуальное адресное пространство исчерпано.

(Еще один эксперимент - закомментировать перераспределение, чтобы память не освобождалась и не перераспределялась. Приложение терпит неудачу в точно таком же месте: После 38 итераций. Единственное отличие в том, что на этот раз диспетчер задач отражает использование полных 2 ГБ.)

И последнее замечание: Это же приложение работает под Linux. Так что эта realloc() проблема исключительно Windows.

Есть мысли?

6
задан asheffie 6 February 2012 в 18:00
поделиться