2011-04-03 21 views
10

Uso las rutinas AllocMem/GetMem/New para asignar memoria, luego uso las rutinas FreeMem/Dispose para liberar memoria. Pero encontré (por Process Explorer) que el tamaño de la memoria del proceso no se redujo.¿Por qué usar rutinas FreeMem/Dispose para liberar memoria, pero no hay memoria reducida?

Si uso las API GlobalAllocPtr/HeapAlloc y GlobalFreePtr/HeapFree, el tamaño de la memoria se reducirá.

Aquí está mi código de prueba:

type 
    TMyRec = record 
    Name: string; 
    TickCount: Cardinal; 
    Buf: array[0..1024 - 1] of byte; 
    end; 
    PMyRec = ^TMyRec; 

var 
    Form1: TForm1; 

implementation 

{$R *.dfm} 

procedure TForm1.FormDestroy(Sender: TObject); 
begin 
    FList.Free; 
end; 

procedure TForm1.FormCreate(Sender: TObject); 
begin 
    FList := TList.Create; 
    ReportMemoryLeaksOnShutdown := true; 
end; 

procedure TForm1.Button1Click(Sender: TObject); 
var 
    i: Integer; 
    Size: Integer; 
    Rec: PMyRec; 
    Heap: Cardinal; 
begin 
    Size := SizeOf(TMyRec); 
    Heap := GetProcessHeap; 
    for I := 0 to 2000 - 1 do 
    begin 
    Rec := AllocMem(Size);        // Delphi routine 
    //GetMem(Rec, Size);        // Delphi routine 
    //New(Rec);           // Delphi routine 

    //Rec := GlobalAllocPtr(GPTR, Size);    // Windows API 
    //Rec := HeapAlloc(Heap, HEAP_ZERO_MEMORY, Size); // Windows API 
    FList.Add(Rec); 
    end; 
end; 

procedure TForm1.Button2Click(Sender: TObject); 
var 
    i: Integer; 
    Size: Integer; 
    Rec: PMyRec; 
    Heap: Cardinal; 
begin 
    Size := SizeOf(TMyRec); 
    Heap := GetProcessHeap; 
    for i := FList.Count - 1 downto 0 do 
    begin 
    Rec := PMyRec(FList.Items[i]); 
    FreeMem(Rec, Size);   // Delphi routine 
    //Dispose(Rec);    // Delphi routine 

    //GlobalFreePtr(Rec);   // Windows API 
    //HeapFree(Heap, 0, Rec);  // Windows API 
    end; 
    FList.Clear; 
end; 
+1

Esta es una buena pregunta (TM). Debería ser wiki de la comunidad. –

Respuesta

24

Así funciona el administrador de memoria Delphi: admite su propio caché de memoria para que no devuelva todas las memorias liberadas al sistema, sino que las mantiene en el caché. La próxima vez que asigna una memoria, primero intenta encontrar la memoria solicitada en la memoria caché, no en el sistema. Eso hace que la asignación/desasignación de memoria sea más rápida.

BTW nunca use FreeMem para registros con campos administrados de por vida (ej. Cadenas, como en su ejemplo) - conduce a pérdidas de memoria. Use Dispose en su lugar.

Además, nunca use GetMem para registros con campos administrados de por vida (línea comentada en su ejemplo) - esto lleva a violaciones de acceso. Use New.

+5

+1 para la advertencia sobre el uso de Dispose/New para dichos registros. –

1

No debe especificar Tamaño de funcionar FreeMem. Solo requiere un parámetro: puntero. De lo contrario, su código se ve bien. Me pregunto: ¿por qué está utilizando malloc y gratis en lugar de nuevo y eliminar/eliminar? O GetMem y FreeMem.

+7

No he votado negativamente porque eres nuevo, pero esta no es una respuesta útil porque no responde a la pregunta. Debes eliminarlo para no obtener más votos negativos. –

+0

+1 "Esta respuesta es útil" –

11

Estás viendo esto porque obtener memoria de Windows es una operación costosa, así que cuando usas el administrador de memoria incorporado de Delphi, guarda en memoria cierta cantidad de memoria no utilizada, ya que es probable que la necesites otra vez pronto .

Si libera mucha memoria, probablemente verá que le devuelve algo al sistema operativo, pero aún conserva algo localmente, por lo que no tendrá que pedir más tan pronto.

+4

Al menos el OP no está utilizando el Administrador de tareas para medir la memoria. No verá una diferencia en ninguna herramienta externa, como dice Mason, hasta que libere lo suficiente como para que el administrador de montón (mm rápido) decida reducir su grupo de almacenamiento dinámico. –

2

El administrador de memoria de Delphi realmente asigna/libera memoria por páginas.

Cuestiones relacionadas