2011-04-03 14 views
10

Belleği ayırmak için AllocMem/GetMem/New rutinlerini kullanıyorum, ardından belleği serbest bırakmak için FreeMem/Dispose rutinlerini kullanın. Ancak (Process Explorer tarafından) işlemin bellek boyutunun azaltılmadığını buldum.Belleği serbest bırakmak için neden FreeMem/Dispose yordamlarını kullanıyorsunuz, ancak bellek azalmıyor?

GlobalAllocPtr/HeapAlloc ve GlobalFreePtr/HeapFree API'lerini kullanırsam, bellek boyutu azalır.

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

Bu Güzel Bir Soru (TM). Topluluk vikisi olmalı. –

cevap

24

Delphi bellek yöneticisinin işleyiş şekli budur - her bir boş belleğin sisteme geri dönmemesi için ön bellek önbelleğinde tuttuğu kendi bellek önbelleğini destekler. Bir dahaki sefere sistemde değil, önbellekte istenen belleği bulmak için ilk önce denediği bir bellek ayırır. Bu bellek ayırma/ayrılma işlemini daha hızlı yapar.

BTW, ömür boyu yönetilen alanlar (örneğinizde olduğu gibi eski dizeler) içeren kayıtlar için asla FreeMem'u kullanmaz - bellek sızıntılarına neden olur. Bunun yerine Dispose kullanın.

Ayrıca, ömür boyu yönetilen alanlar (örneğinizde yorumlanmış satır) içeren kayıtlar için hiçbir zaman GetMem'u kullanmayın - bu, ihlallere erişim sağlar. New kullanın.

+5

+1, bu tür kayıtlar için Dispose/New kullanımıyla ilgili uyarı için. –

1

Sen FreeMem işlevine Boyut belirtmemelidir:

İşte benim test kodudur. Sadece bir parametre alır - işaretçi. Aksi takdirde kodunuz iyi görünüyor. Sadece merak ediyorum - neden yeni ve silme/kullanma yerine malloc ve ücretsiz kullanıyorsunuz? Veya GetMem ve FreeMem.

+7

Bunu reddetmedim çünkü yenisin, ama bu gerçekten yararlı bir cevap değil çünkü sorulan soruya cevap vermiyor. Silmelisin ki daha fazla not almazsın. –

+0

+1 "Bu yanıt yararlıdır" –

11

Bunu görüyorsunuz, çünkü Windows'dan bellek almak pahalı bir işlemdir, bu yüzden Delphi'nin yerleşik bellek yöneticisini kullandığınızda, belirli bir miktar kullanılmayan bellek önbelleğe alır, çünkü yakında başka bir şey için tekrar ihtiyacınız olabilir .

Çok fazla bellek boşalttığınızda büyük olasılıkla işletim sistemine geri döndüğünü görürsünüz, ancak bazılarını hala yerel olarak tutar, bu nedenle daha fazla sormak zorunda kalmazsınız.

+4

En azından OP belleği ölçmek için Görev Yöneticisi kullanmıyor. Mason'un dediği gibi, herhangi bir harici araçta, yığın yöneticisinin (hızlı mm) yığın havuzunu azaltmaya karar verene kadar bir fark görmeyeceksiniz. –

2

Delphi bellek yöneticisi, belleği sayfalara ayırır/boşaltır.

İlgili konular