2012-09-29 33 views
5

Tengo un pedazo de código de DelphiCómo liberar memoria cuando se produce una excepción fuera de la memoria en 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; 

El código anterior intenta asignar una gran cantidad de memoria y out-of-memory van a detener. Se ejecutará a=nil, pero la memoria no se libera.

¿Hay alguna forma de liberar la memoria en el caso de una excepción de falta de memoria?

Intenté SetLength(a, 0, 0, 0) y Finalize(a), y ambos tampoco funcionarán.

+0

Cuando está en el manejador de excepciones, ¿'a' incluso tiene un valor no nulo? Si no, entonces no se puede esperar poder liberarlo. Además, se liberará al final de la función de todos modos. ¿Has confirmado que 'SetLength' establece la variable' a' cuando no puede terminar de asignar toda la memoria solicitada? –

+0

@Rob No, 'a' es' nil' en el manejador de excepciones. –

+0

Sí, a = nil cuando el código entra al bloque de excepción. PD: utilicé FastMM como administrador de memoria. –

Respuesta

7

En general, no es posible recuperar desde un error de falta de memoria. En ese punto, es muy probable que el montón esté dañado. La respuesta apropiada es terminar el proceso. En este caso específico, la asignación se realiza por DynArraySetLength en la unidad System. Esto realiza asignaciones repetidas. Solo como el último acto de DynArraySetLength es el valor de retorno, a en su código anterior, realmente asignado. Y si se producen errores en DynArraySetLength, entonces el tiempo de ejecución no hace ningún esfuerzo para poner en orden. Lo que significa que en caso de falla, cualquier memoria asignada se filtra y no se puede recuperar. No tiene forma de consultarlo para liberarlo.

Puede pensar que DynArraySetLength debería hacer más para poner en orden. Sin embargo, su enfoque es justificable. Dado que las condiciones de falta de memoria invariablemente resultan en un montón corrupto, los intentos de ordenar simplemente prolongarían la agonía. Una vez que el montón está muerto, no tiene sentido tratar de desasignar la memoria.

+1

La pregunta natural de seguimiento es '¿Hay un procedimiento 'TrySetLength'?' –

+1

@AndreasRejbrand No, no hay. –

+0

¿Estás seguro? Piensa que depende de las funciones internas del administrador de memoria si el montón está dañado o no. – kludg

Cuestiones relacionadas