2012-09-29 18 views
5

Ho un pezzo di codice DelphiCome liberare la memoria quando si verifica Out-of-memory eccezione in Delphi usando SetLength

var 
    a: array of array of array of integer; 
begin 
    try 
    SetLength(a, 100000, 100000, 10000); // out of memory here 
    doStuffs(a); 
    except 
    a = nil; // try to free the memory 
    end; 
end; 

Il codice di cui sopra tenta di allocare molta memoria e saranno catturati out-of-memory. Il a=nil verrà eseguito, ma la memoria non viene liberata.

C'è un modo per liberare la memoria nel caso di un'eccezione di memoria insufficiente?

Ho provato SetLength(a, 0, 0, 0) e Finalize(a), ed entrambi non funzioneranno neanche.

+0

Quando sei nel gestore di eccezioni, 'a' ha anche un valore non nullo? In caso contrario, non puoi certo aspettarti di essere in grado di liberarlo. Inoltre, sarà comunque liberato alla fine della funzione. Hai confermato che "SetLength" imposta la variabile 'a' quando non riesce a terminare l'allocazione di tutta la memoria richiesta? –

+0

@Rob No, 'a' è' nil' nel gestore delle eccezioni. –

+0

Sì, a = zero quando il codice entra nel blocco di eccezioni. PS: ho usato il FastMM come gestore della memoria. –

risposta

7

In generale, non è possibile ripristinare da un errore di memoria insufficiente. A quel punto l'heap è probabilmente danneggiato. La risposta appropriata è terminare il processo.

In questo caso specifico, l'assegnazione viene eseguita da DynArraySetLength nell'unità System. Questo esegue assegnazioni ripetute. Solo come ultimo atto di DynArraySetLength è il valore restituito, a nel tuo codice sopra, effettivamente assegnato. E se gli errori si verificano in DynArraySetLength allora il runtime non fa sforzo per riordinare. Il che significa che in caso di errore, qualsiasi memoria allocata è trapelata e non può essere recuperata. Non hai modo di fare riferimento ad esso per liberarlo.

Si potrebbe pensare che DynArraySetLength dovrebbe fare di più per riordinare. Tuttavia, l'approccio è giustificabile. Poiché le condizioni di memoria invariabilmente si traducono in un heap corrotto, i tentativi di riordinare non farebbero altro che prolungare l'agonia. Una volta che l'heap è morto, non ha senso tentare di deallocare la memoria.

+1

La domanda di follow-up naturale è "Esiste una procedura' TrySetLength'? " –

+1

@AndreasRejbrand No, non c'è. –

+0

Sei sicuro? Pensa che dipenda dagli interni del gestore della memoria se l'heap è corrotto o meno. – kludg