2015-05-29 35 views
0

我在下面的代碼中顯示用戶類的簡短設計模式。內存泄漏與訪問衝突,類設計問題

type 
    MytestClass = class 
    alist: TStringlist; 
    public 
    constructor Create; 
    destructor destroy; override; 
    end; 
    { MytestClass } 

type 
    TForm1 = class(TForm) 
    btn_version01: TBitBtn; 
    btnversion02: TBitBtn; 
    procedure FormClose(Sender: TObject; var Action: TCloseAction); 
    procedure FormCreate(Sender: TObject); 
    procedure btn_version01Click(Sender: TObject); 
    procedure btnversion02Click(Sender: TObject); 
    private 
    { Private-Deklarationen } 
    public 
    { Public-Deklarationen } 

    btestClass : MytestClass; 
    aComplexClassDesign : TComplexClassDesign; 
    end; 

var 
    Form1: TForm1; 

implementation 

{$R *.dfm} 

constructor MytestClass.Create; 
begin 
    alist := TStringlist.Create; 
end; 

destructor MytestClass.destroy; 
begin 
    alist.free; 
    inherited; 
end; 


procedure TForm1.btnversion02Click(Sender: TObject); 
var atestClass : MytestClass; 
begin 
    /// 
    atestClass :=MytestClass.Create; 
    atestClass.Free; 
    atestClass := nil; 
end; 

procedure TForm1.btn_version01Click(Sender: TObject); 
var atestClass : MytestClass; 
begin 
    /// 
    atestClass :=MytestClass.Create; 
    atestClass.Free; 
end; 

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction); 
begin 
    btestClass.free; 
    aComplexClassDesign.Free; 
end; 

procedure TForm1.FormCreate(Sender: TObject); 
begin 
    btestClass :=MytestClass.Create; 
    aComplexClassDesign :=TComplexClassDesign.Create; 
end; 

end. 

希望這是一個沒有內存泄漏和訪問衝突的完美設計。我在真實應用程序中使用的所有類都是按照這種模式設計的。

在上面的代碼中,FastMM4不會在我的TComplexClassDesign中顯示任何問題。在實際應用程序中,FASTMM4報告了我的TComplexClassDesign的內存泄漏,即使我在窗體的Close事件中調用了自由函數。如果我通過代碼確定執行此功能。 任何想法如何調試此內存泄漏報告,任何選項來查看尚未發佈的TComplexClassDesign的實例?爲什麼我得到這個奇怪的內存泄漏報告的其他原因?

獎金的問題:

DUNIT總是這樣

atestClass :=MytestClass.Create; 
    atestClass.Free; 
    atestClass := Nil 

拆解代碼是真正需要的代碼的最後一行?

+0

'>是最後一行代碼真正需要的?'。不,這是不需要的。如果變量'atestClass'被重用,最好不要使用它,否則不會。多年來一直在討論很多,因爲在某些情況下它可以使調試變得更容易。搜索'FreeAndNil()'。 [哪一個更好:Free或FreeAndNil?](http://stackoverflow.com/questions/3159376/which-is-preferable-free-or-freeandnil)。 –

回答

-1

獎金答案:

atestClass仍然會指向一個內存地址,即使你所謂的自由。如果您在免費調用後嘗試訪問內存,則可能正在訪問錯誤的數據(如果其他內容正在使用該內存位置),或者如果內存不再可訪問,則會訪問衝突。

如果免費是一個函數的最後一行,然後退出/那麼可能不需要回報吧...

+0

即時消息 - 接受的答案應該切換到大衛給的,但降低投票或投票刪除這個答案是不正確的。 –

+0

@Lieven我覺得有趣的是downvoting經常遭到批評,但很少被批評。人們想知道爲什麼不對稱。 –

+0

我想這是所有關於[正負反饋](https://www.psychologytoday.com/blog/happiness-in-world/201309/which-kind-feedback-is-best),但在這種情況下:這個答案是「沒有錯」。問題在於問題和接受的答案是什麼,但是這不是@mbrandeis對我這樣做,沒有意義的下降。 –

7

這是一個錯誤與OnClose匹配OnCreate。這些事件不是一對。在施工期間調用OnCreate事件。銷燬的匹配事件是OnDestroy。您在OnCreate中創建的任何內容均應在OnDestroy內銷燬。

我個人看到OnCreateOnDestroy的價值很小。我會一直選擇重載虛擬構造函數和析構函數。


procedure TForm1.FormCreate(Sender: TObject); 
begin 
    btestClass :=MytestClass.Create; 
    aComplexClassDesign :=TComplexClassDesign.Create; 
end; 

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction); 
begin 
    btestClass.free; 
    aComplexClassDesign.Free; 
end; 

作爲一般規則,破壞創造相反的順序對象。這裏沒關係,但如果對象有依賴關係,那麼順序有時很重要。


procedure TForm1.btnversion02Click(Sender: TObject); 
var atestClass : MytestClass; 
begin 
    atestClass :=MytestClass.Create; 
    atestClass.Free; 
    atestClass := nil; 
end; 

是否有任何點分配到nilatestClass?絕對不。這個變量在作業之後立即離開作用域,因此結果分配不能被任何其他代碼觀察到。我希望編譯器對此提出警告。它會在您進行分配時發出警告,但從未使用分配的值。我希望你已經啓用了警告。


最後,爲什麼你真正的代碼有內存泄漏?不可能從這裏告訴。 FastMM的完整調試版本爲泄漏報告提供了豐富的堆棧跟蹤信息。這些痕跡將包括導致泄漏對象分配的調用堆棧。

+2

lol - 當你需要做的就是回答* bonus *問題時,爲什麼還要爲* actual *問題寫一個詳細的答案。 –

+0

是的,我不知道爲什麼我的答案被標記爲接受的答案。顯然我沒有回答主要問題,我也沒有聲稱自己是。我清楚地表明我正試圖回答獎金問題。至於downvotes或upvotes,我沒有參與任何部分。因爲社區不喜歡我的回答被接受,所以得到低估是很奇怪的。是的,這不是主要問題的正確答案,但可以通過確定接受的答案來解決。 – mbrandeis