2012-08-30 51 views
6

德爾福有一個基本的疑問。當我把任何部件在設計時,例如說TADOConnectuion和按一下按鈕,即使我寫下面的代碼,然後我沒有得到任何錯誤:德爾福中「免費」的基本原理

begin 
    ADOConnection.Free; //No error 
    ADOConnection.Free; //No error 
    ADOConnection.Free; //No error 
end; 

但是,如果我在運行時創建相同的對象follwos我得到「訪問衝突...」錯誤

begin 
    ADOConnection := TADOConnection.create(self); 
    ADOConnection.Free; //No error 
    ADOConnection.Free; //Getting an "Access Violation..." error 
end; 

我得到同樣的錯誤,即使我創建對象如下:

ADOConnection := TADOConnection.create(nil); 

只是想知道後面這種行爲的原因,即。爲什麼在設計時保留組件時沒有錯誤?

+1

相關:[爲什麼不FreeAndNil * *真nil我的對象?](http://stackoverflow.com/questions/8036388/delphi-why-doesnt-freeandnil-really-nil-my-object) – CodesInChaos

+0

Vishal,它沒有用(實際上它是灰心)添加禮讓公式在這裏你的問題和答案。 – mghie

回答

4

如果您釋放組件,則其所有者中的相應字段將被清除。如果添加了設計時ADOConnection,然後

ADOConnection.Free; // Frees ADOConnection and sets ADOConnection to nil 
ADOConnection.Free; // Does nothing since ADOConnection is nil 

您可以通過在一個變量捕獲它看到:

var c: TADOConnection; 
c := ADOConnection; 
c.Free; // Frees ADOConnection and sets ADOConnection to nil 
c.Free; // Error: c is not set to nil 

這是行不通的,即使在設計時創建ADOConnection

這裏有一個TButton組件演示您將看到設計時組件的行爲是多麼的不具體設計時組件的例子:

unit Unit1; 

interface 

uses 
    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
    Dialogs, StdCtrls; 

type 
    TForm1 = class(TForm) 
    procedure FormCreate(Sender: TObject); 
    published 
    Button: TButton; 
    end; 

var 
    Form1: TForm1; 

implementation 

{$R *.dfm} 

procedure TForm1.FormCreate(Sender: TObject); 
begin 
    Assert(not Assigned(Button)); 
    TButton.Create(Self).Name := 'Button'; // Button field gets set 
    Assert(Assigned(Button)); 
    Button.Free;       // Button field gets cleared 
    Assert(not Assigned(Button)); 
    Button.Free;       // Okay, Free may be called on nil values 
end; 

end. 
+1

最後一個疑問,爲什麼這樣的行爲需要設計時間和運行時間 ? –

+0

@VishalTiwari差別不在於設計時間和運行時間之間,而是在擁有者和非擁有者之間。我會稍微介紹一個例子。 – hvd

+1

將ADOConnection設置爲零的相關代碼位於TComponent.SetReference中,它與Free沒有直接關係,但更多的是RemoveComponent(在Destroy內部調用)。當所有者擁有一個名稱與子組件類似的字段時,該機制起作用。 –

3

ADOConnection最初是零,所以如果你釋放它,自由函數將不會做任何事情,因爲交給它的指針是零。指針在隨後的調用中保持零,所以free保持不動。當您使用create初始化ADOConnection時,ADOConnection中保存的指針不再爲零,因此第一次釋放的指針將主動釋放指針,但隨後的調用將看到內存已被釋放並引發異常。指針不會被通話改變爲空閒。爲此,你需要freeandnil。

+0

但有些時候FreeAndNil函數在沒有任何原因的情況下也會出現「Access Violation ...」錯誤,這就是我一直在使用的原因。免費 –

+1

@VishalTiwari:你真的看了FreeAndNil中的代碼嗎?這種訪問衝突絕對是來自某處,但我不明白它是如何由FreeAndNil而不是Free造成的...... –

+0

@VishalTiwari:那種非零無效的引用被稱爲*陳舊的指針*。除非析構函數寫得太差,否則會拋出一個未處理的AV異常,我記得使FreeAndNil拋出一個AV的唯一方法就是傳遞一個陳舊的指針.... –