2012-08-30 25 views
6

Tôi có một nghi ngờ cơ bản trong Delphi. Khi tôi giữ bất kỳ thành phần lúc thiết kế, nói ví dụ TADOConnectuion và trên nút nhấp chuột ngay cả tôi viết sau mã sau đó tôi không nhận được bất kỳ lỗi:Cơ bản của "Tự do" trong Delphi

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

Nhưng nếu tôi tạo ra cùng một đối tượng tại thời gian chạy như follwos tôi nhận được "truy cập vi phạm ..." lỗi

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

tôi nhận được lỗi tương tự mặc dù tôi tạo ra các đối tượng như sau:

ADOConnection := TADOConnection.create(nil); 

Chỉ cần muốn biết lý do đằng sau hành vi như vậy, tức là Tại sao không có lỗi khi tôi giữ thành phần tại thời điểm thiết kế?

+1

liên quan: [tại sao không FreeAndNil * thực sự * nil đối tượng của tôi?] (http://stackoverflow.com/questions/8036388/delphi-why-doesnt-freeandnil-really-nil-my-object) – CodesInChaos

+0

Vishal, nó không hữu ích (trên thực tế nó không được khuyến khích) để thêm công thức lịch sự cho câu hỏi và câu trả lời của bạn ở đây trên SO. – mghie

Trả lời

4

Nếu bạn giải phóng một thành phần, trường tương ứng của nó trong chủ sở hữu sẽ bị xóa. Nếu bạn thêm một thời gian thiết kế ADOConnection, sau đó

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

Bạn có thể thấy điều này bằng cách bắt nó trong một biến:

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

Điều đó sẽ không làm việc, ngay cả khi ADOConnection được tạo ra vào thời điểm thiết kế.

Dưới đây là một ví dụ với một thành phần TButton thể hiện như thế nào hành vi mà bạn nhìn thấy cho các thành phần thiết kế thời gian không phải là cụ thể để thiết kế thời gian thành phần:

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

nghi ngờ cuối cùng, tại sao hành vi như vậy cho thời gian thiết kế và chạy thời gian ? –

+0

@VishalTiwari Sự khác biệt không thực sự giữa thời gian thiết kế và thời gian chạy, nó nằm giữa sở hữu và không được công nhận. Tôi sẽ bao gồm một ví dụ trong một chút. – hvd

+1

Các mã có liên quan thiết lập ADOConnection để nil là trong TComponent.SetReference và nó không liên quan trực tiếp đến miễn phí, nhưng nhiều hơn để RemoveComponent (được gọi là bên trong Destroy). Cơ chế này hoạt động khi chủ sở hữu có một trường được đặt tên giống như thành phần con. –

3

Kết nối ADOC ban đầu là không, vì vậy nếu bạn giải phóng nó, chức năng miễn phí sẽ không làm bất cứ điều gì vì con trỏ giao cho nó là không. Con trỏ vẫn giữ nguyên trong các cuộc gọi tiếp theo, vì vậy miễn phí không làm gì cả. Khi bạn khởi tạo ADOConnection bằng tạo, con trỏ được giữ trong ADOConnection không còn nil nữa, vì vậy cuộc gọi đầu tiên miễn phí sẽ chủ động giải phóng con trỏ, nhưng các cuộc gọi tiếp theo sẽ thấy rằng bộ nhớ đã được giải phóng và tăng một ngoại lệ. Con trỏ không bị thay đổi bởi cuộc gọi miễn phí. Cho rằng, bạn cần freeandnil thay thế.

+0

Nhưng một số lần chức năng FreeAndNil cũng cho lỗi "Vi phạm Truy cập ..." mà không có lý do nào, đó là lý do tại sao tôi làm việc với .Free –

+1

@VishalTiwari: Bạn đã thực sự xem xét mã trong FreeAndNil chưa? Vi phạm truy cập đó chắc chắn đến từ đâu đó, nhưng tôi không thấy nó có thể được gây ra bởi FreeAndNil và không phải bởi Free ... –

+0

@VishalTiwari: loại tham chiếu không hợp lệ không được gọi là * con trỏ cũ *. Trừ khi destructor là xấu như vậy bằng văn bản mà nó ném một ngoại lệ AV unhandled, cách duy nhất tôi nhớ để làm cho FreeAndNil ném một AV là để vượt qua nó một con trỏ cũ .... –

Các vấn đề liên quan