2011-03-05 93 views
4

我必須錯過一些相當簡單的東西嗎?我試圖在Delphi 3應用程序中創建一個鏈表。德爾福3內存分配問題

這是通過兩個類別項目列表項目ItemList在表單創建時實例化。它堅持一生的形式。每個項目對象根據需要被實例化。該表格有一個稱爲AddAcc的功能。 AddAcc通過窗體控件之一的on-change事件調用。

本上改變事件中會發生什麼:

  1. AddAcc
  2. AddAcc創建一個新的項目對象
  3. AccAdd電話ItemList.AddItem商品通過參考
  4. 的AddItem地方項目在

我測試過的AddItem和它運作良好列表的尾部對象。我的問題是,每次* AddAcc *被調用它獲得相同的內存位置。我試過用不同的方法創建一個新的項目對象。我使用了New,GetMem(w/FillChar),並實例化了一個Item類型的局部變量。所有對AddAcc的調用都會導致獲得相同的內存位置。

我直接傳遞的項目對象(通過引用)的AddItem和可選地通過一個指針對象。

我認爲鏈接列表中的對象Item的實例的引用(指針)將確保項目的內存位置將被保持。然而,看起來,一旦退出類,它就會被收集起來。

FUNCTION AddAcc; 

Var 

    accItem : ptrItem; 

BEGIN 

    GetMem(accItem, sizeOf(Item)); 

    FillChar(accItem^, sizeof(Item), 0); 

    ItemList.AddItem(accItem^); 

End; 



Procedure TItemList.AddItem(Var newItem : TAccessoryItem); 

begin 
    Inc(_count); 

    // add first item to the list    
    If (_count = 1) Then 
    begin  

      _fifoHead := @newItem; 
      _tail := @newItem; 
      newItem.Next := @_tail; 
      newItem.Previous := @_fifoHead; 
      exit; 

    end; 

    _tail^.Next := @newItem; 
    newItem.Previous := _tail^; 
    mewItem.Next := @_tail; 
    _tail := @newItem;   
end; 

任何幫助,非常感謝。

+1

請給我們一些代碼。一旦我們看到你的代碼,我們會告訴你它有什麼問題。 – 2011-03-05 12:48:49

+0

請發佈調用AddAcc的代碼的代碼,AddAcc方法本身,聲明ListItem對象的代碼行以及初始化它的代碼行。基本上,聲明,初始化,AddAcc +至少有一個調用AddAcc的地方(以及調用它的方法的所有代碼,而不僅僅是調用它的代碼行) – 2011-03-05 12:49:04

+1

我可以猜測你傳遞的地址是一個包含指針的局部變量。 – 2011-03-05 12:50:57

回答

1

以下是我會寫一個鏈表:

type 
    PItem = ^TItem; 
    TItem = record 
    Next: PItem; 
    Data: Integer; 
    end; 

procedure Add(var First: PItem; Data: Integer); 
var 
    NewItem: PItem; 
begin 
    New(NewItem); 
    NewItem.Next := First; 
    NewItem.Data := Data; 
    First := NewItem; 
end; 

... 

var 
    First: PItem; 
begin 
    First := nil; 
    Add(First, 42); 
    //etc. 
end; 

當您需要取消分配列表你這樣做:

var 
    Item: PItem; 
begin 
    while Assigned(First) do begin 
    Item := First; 
    First := Item.Next; 
    Dispose(Item); 
    end; 
end; 

這是我的信念,這是規範的方式在Pascal中編寫鏈接列表類型代碼。

我特意爲可以想象的這個最簡單的鏈表寫了這段代碼。這使您可以專注於分配,使用指針等。您似乎已經知道如何在更復雜的列表中維護引用,所以我相信您可以毫無困難地將這種類型的代碼適應您的需求。

+0

謝謝大衛,這有助於。我簡化了代碼,使其更符合您提供的內容。在這樣做的時候,我將AddItem和列表頭部和尾部指針移出ItemList並放入包含AddAcc的單元中。出於某種原因,這允許維護列表中的每個節點的內存(而不是垃圾收集)。我將在今天晚上更充分地調查這一點並評論我的發現......我感謝幫助! – 2011-03-05 15:03:21

+1

@mad moe,只是爲了澄清:Delphi不會做垃圾回收。你的代碼很糟糕;你錯誤地調用了AddItem(使用'accItem ^',它是accItem的* content *)而不是內存塊的地址('accItem'本身 - 注意缺失的解引用運算符^),你錯誤地在addItem中用' var',這意味着您可以更改*地址*以及內容​​,然後錯誤地使用addItem中的地址(@)運算符。 Delphi不是C#或VB.NET或Java;它不會執行垃圾回收 - 您需要自己管理它。 :-) – 2011-03-05 15:30:29

+0

@Ken謝謝。我沒有試圖深入研究OP的代碼,因爲我覺得最好從一個乾淨的石板開始。 – 2011-03-05 15:45:55