Sto tentando di utilizzare realloc() in un'applicazione Windows. Sto allocando un grande blocco di memoria, quindi usando realloc() per ridurlo più tardi una volta che conosco la dimensione corretta.Realloc() non libera correttamente la memoria in Windows
Sto trovando che sebbene realloc() sembra funzionare correttamente (la memoria in Task Manager riflette ciò che ci si aspetterebbe) l'applicazione alla fine esaurisce la memoria. Da quello che posso dire, è come se relloc() libera la memoria ma non libera lo spazio di indirizzo virtuale associato alla memoria. Di conseguenza, lo malloc() non funzionerà.
Ecco una piccola applicazione console che illustra il problema:
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;
}
L'applicazione assegna ripetutamente 50 MB di memoria e poi subito ridimensiona essere solo 10K. Se lo esegui, troverai che fallisce con un errore OUT OF MEMORY dopo solo 38 iterazioni. Ciò corrisponde a 2 GB di memoria allocata in origine, ovvero il limite di spazio degli indirizzi per le applicazioni Windows.
È interessante notare che, se si cerca in Task Manager, l'applicazione non richiede quasi memoria. Eppure malloc() non funziona. Questo è ciò che mi porta a credere che lo spazio virtuale degli indirizzi sia esaurito.
(Un altro esperimento per provare è quello di commentare la riallocazione, in modo che nessun memoria viene liberata o riassegnati L'applicazione non riesce esattamente nello stesso posto:.. Dopo 38 iterazioni L'unica differenza è che questa volta Task Manager riflette il pieno 2GB in uso.)
Un ultimo punto di informazioni: questa stessa applicazione funziona sotto Linux. Quindi questo problema di realloc() è strettamente solo per Windows.
Qualche idea?
Qual è la tua domanda? – ikegami
La mia domanda? Immagino che "questo comportamento sia un bug noto in Windows?" E ovviamente, c'è qualche soluzione per questo problema che non implica la copia della memoria? – asheffie
Ad ogni modo, probabilmente hai un problema di progettazione fondamentale, certamente per i processi che metteranno a dura prova lo spazio degli indirizzi a 32 bit. Dici "Sto allocando un grande blocco di memoria, quindi usando realloc() per ridurlo più tardi una volta che conosco la dimensione corretta." Questo è solo un problema. È molto impegnativo richiedere blocchi contigui di spazio indirizzi molto grandi. Sta molto meglio allocando piccoli pezzi di memoria e poi unendoli insieme. –