Я пытаюсь использовать 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.
Есть мысли?