2015-11-16 23 views
1

附加是我正在運行的內存泄漏示例的完整代碼。有人可以告訴我如何清理這個內存泄漏。如果您創建表單並在其上放置按鈕,然後將以下代碼粘貼到.pas文件中,則可以編譯此代碼。預先感謝任何可以提供的幫助。使用tlist完整Delphi代碼中的內存泄漏

unit LeakForm; 

interface 

uses 
    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
    Dialogs, StdCtrls; 
type PrintRecord = record 
    PrintString1, 
    PrintString2, 
    PrintString3, 
    PrintString4, 
    PrintString5, 
    PrintString6 : string; 
    PrintFloat1, 
    PrintFloat2, 
    PrintFloat3 : Double; 
end; 
PrintPointer = ^PrintRecord; 

type 
    TForm1 = class(TForm) 
    Button1: TButton; 
    procedure Button1Click(Sender: TObject); 
    procedure FormCreate(Sender: TObject); 
    procedure FormClose(Sender: TObject; var Action: TCloseAction); 
    private 
    { Private declarations } 
    MyPrintLst : TList; 
    public 
    { Public declarations } 
    end; 

var 
    Form1: TForm1; 

implementation 

{$R *.dfm} 
procedure ClearTList(Var List : TList); 
Var I, Count : Integer; 
begin 
    Count := list.Count - 1; 
    For I := Count DownTo 0 Do 
    Dispose(List[I]); 
    List.Clear; 
end; 
procedure FreeTList(Var List : TList); 
Var I, Count : Integer; 
begin 
    ClearTList(List); 
    List.Free; 
end; 
procedure AddToPrintList(PrintList : TList; 
         Const MyStrings : Array of String; 
         Const MyDoubles : Array of Double); 
var 
PrintPtr : PrintPointer; 
begin 
New(PrintPtr); 
IF High(MyStrings) >= 0 Then 
    PrintPtr^.printString1 := MyStrings[0]; 
Begin 
    IF High(MyStrings) >= 1 Then 
    Begin 
     PrintPtr^.printString2 := MyStrings[1]; 
     IF High(MyStrings) >= 2 Then 
     Begin 
     PrintPtr^.printString3 := MyStrings[2]; 
     IF High(MyStrings) >= 3 Then 
      Begin 
      PrintPtr^.printString4 := MyStrings[3]; 
      IF High(MyStrings) >= 4 Then 
       PrintPtr^.printString5 := MyStrings[4]; 
      Begin 
       IF High(MyStrings) >= 5 Then 
        PrintPtr^.printString6 := MyStrings[5]; 
      End; {>=5} 
      End; {>=4} 
     End; {>=3} 
    End; {>=2} 
End; {>=1} 
IF High(MyDoubles) >= 0 Then 
Begin 
    PrintPtr^.PrintFloat1 := MyDoubles[0]; 
    IF High(MyDoubles) >= 1 Then 
    Begin 
     PrintPtr^.PrintFloat2 := MyDoubles[1]; 
     IF High(MyDoubles) >= 2 Then 
     PrintPtr^.PrintFloat3 := MyDoubles[2]; 
    End; 
End; 
PrintList.add(PrintPtr); 
end; 
procedure TForm1.Button1Click(Sender: TObject); 
Var EstReading : LongInt; 
begin 
EstReading := 0; 
ClearTList(MyPrintLst); 
AddToPrintList(MyPrintLst, ['Field1 Data','Field2 Data','Field3 Data','Field4 Data'], 
          [1,2,3,4]); 
AddToPrintList(MyPrintLst, ['Field1 Data','Field2 Data','Field3 Data','Field4 Data'], 
          [5,6,7,8]); 
AddToPrintList(MyPrintLst, ['Field1 Data','Field2 Data','Field3 Data','Field4 Data'], 
          [9,0,1,2]); 
AddToPrintList(MyPrintLst, ['Field1 Data','Field2 Data','Field3 Data','Field4 Data'], 
          [3,4,5,6]); 
end; 

procedure TForm1.FormCreate(Sender: TObject); 
begin 
    MyPrintLst := TList.Create; 
end; 

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction); 
begin 
FreeTList(MyPrintLst); 
end; 

end. 
+1

獎金的問題:有多少貓=^^ =在源代碼隱藏? – mjn

+0

只是一個無恥的插件:[尋址指針](http://rvelthuis.de/articles/articles-pointers.html)會告訴你爲什麼它不像預期的那樣工作,還有更多。 –

+0

只是一些友好的批評。你在AddToPrintList中的編碼是草率的。您對printString1的分配應該在開始之後;不在之前。並且您在結束後的評論與錯誤的if語句匹配,例如{> = 5}實際上與> = 4的測試匹配。 –

回答

5

當您處置每個項目時,運行時需要知道記錄的類型。由於您使用的是TList,因此每個項目都是無類型的指針。因此,您需要將指針轉換爲該項目類型,以便運行時知道該類型,並知道如何處理該項目。

更換

Dispose(List[I]); 

Dispose(PrintPointer(List[I])); 

這也是有些奇怪,你通過列表​​作爲變量參數和不修改的參考。循環也很奇怪,沒有理由倒退,循環邊界以奇怪的方式處理。我有這些功能是這樣的:

procedure ClearTList(List: TList); 
Var 
    I: Integer; 
begin 
    For I := 0 to List.Count - 1 Do 
    Dispose(PrintPointer(List[I])); 
    List.Clear; 
end; 

procedure FreeTList(List: TList); 
begin 
    ClearTList(List); 
    List.Free; 
end; 

一個更傳統的命名規則是:

type 
    TPrintRecord = record 
    .... 
    end; 
    PPrintRecord = ^TPrintRecord; 

形式的OnClose事件可以被多次調用如果表單有caHide動作結束時。與OnCreate配對的正確事件是OnDestroy

AddToPrintList中邏輯的複雜性使我相信可以更好地設計數據類型。數組暗示他們自己而不是個別編號的領域。

不改變類型,你至少應該避免所有的壓痕,就像這樣:

procedure AddToPrintList(PrintList: TList; const MyStrings: array of String; 
    const MyDoubles: array of Double); 
var 
    I: Integer; 
    Item: PPrintRecord; 
    Str: string; 
    Value: Double; 
begin 
    New(Item); 
    PrintList.Add(Item); 

    for I := 1 to Min(Length(MyStrings), 6) do 
    begin 
    Str := MyStrings[I - 1]; 
    case I of 
    1: 
     Item.PrintString1 := Str; 
    2: 
     Item.PrintString2 := Str; 
    3: 
     Item.PrintString3 := Str; 
    4: 
     Item.PrintString4 := Str; 
    5: 
     Item.PrintString5 := Str; 
    6: 
     Item.PrintString6 := Str; 
    end; 
    end; 

    for I := 1 to Min(Length(MyDoubles), 3) do 
    begin 
    Value := MyDoubles[I - 1]; 
    case I of 
    1: 
     Item.PrintFloat1 := Value; 
    2: 
     Item.PrintFloat2 := Value; 
    3: 
     Item.PrintFloat3 := Value; 
    end; 
    end; 
end;