2012-08-30 3 views
6

나는 델파이에 근본적인 의심을 가지고있다. 내가 디자인 타임에 구성 요소를 유지할 때, 내가 어떤 오류하지 않아도 내가 코드를 다음 쓰기 예를 들어 TADOConnectuion과 버튼 클릭에 대해 말하기를 :델파이의 "자유"근본적인 것

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

을하지만 follwos로 런타임에 동일한 개체를 만드는 경우 I 나는 아래와 같이 객체를 생성하더라도 오류 "... 액세스 위반"나는이 같은 오류가

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

를 얻을 :

ADOConnection := TADOConnection.create(nil); 

그냥 그런 행동 뒤에 이유를 알고 싶습니다, 즉 디자인 타임에 구성 요소를 유지할 때 오류가없는 이유는 무엇입니까?

+1

관련을 : 여기

는 디자인 타임 구성 요소에 대한 참조 행동이-설계 시간 구성 요소를 특정하지 방법을 보여 TButton 구성 요소를 사용하여 예제 nil 내 개체?] (http://stackoverflow.com/questions/8036388/delphi-why-doesnt-freeandnil-really-nil-my-object) – CodesInChaos

+0

Vishal, 공손한 수식을 추가하는 것은 유용하지 않습니다 (실제로는 권장하지 않습니다). 여기에 귀하의 질문과 답변에. – mghie

답변

4

구성 요소를 비우면 소유자의 해당 필드가 지워집니다. 그런 다음,

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

을 디자인 타임 ADOConnection을 추가하면 당신은 변수에 포착하여이를 볼 수 있습니다

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

작동하지 않습니다, ADOConnection 디자인 타임에 생성 된 경우에도. [하지 왜 안 FreeAndNil * 정말 * :

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을 nil로 설정하는 관련 코드는 TComponent.SetReference에 있으며 Free와 직접 관련이 없지만 RemoveComponent (Destroy 내부에서 호출 됨)와 더 관련이 있습니다. 이 메커니즘은 소유자가 자식 구성 요소와 같은 이름의 필드를 가지고있을 때 작동합니다. –

3

ADOConnection은 기본적으로 nil이므로 해제하면 무료 함수는 아무 것도 처리하지 않습니다. 포인터는 후속 호출에서 nil로 유지되므로 free는 아무 것도 수행하지 않습니다. ADOConnection을 create로 초기화하면 ADOConnection에있는 포인터가 더 이상 nil이 아니므로 free에 대한 첫 번째 호출이 포인터를 능동적으로 해제하지만 후속 호출에서는 메모리가 이미 해제되고 예외가 발생하는 것을 볼 수 있습니다. 포인터는 free 호출에 의해 변경되지 않습니다. 그 대신에, 당신은 freeandnil이 필요합니다.

+0

그러나 FreeAndNil 함수는 어떤 이유도없이 "액세스 위반 ..."오류를 발생시킵니다. 그 이유는 바로 내가 함께 작업 한 이유입니다. 무료 –

+1

@VishalTiwari : FreeAndNil의 코드를 실제로 보았습니까? 그 접근 위반은 어딘가에서 오는 것이 확실하지만 FreeAndNil이 아닌 FreeAndNil이 어떻게 발생하는지 알지 못합니다. –

+0

@VishalTiwari : 그 종류의 무효 참조가 부실 포인터 *라고합니다. 소멸자가 처리되지 않은 AV 예외를 던질 정도로 심하게 작성된 경우가 아니라면 FreeAndNil이 AV를 throw하는 것을 기억하는 유일한 방법은 부실 포인터를 전달하는 것입니다. –