2012-08-30 11 views
6

Ho un dubbio fondamentale in Delphi. Quando io continuo a qualsiasi componente in fase di progettazione, diciamo per esempio TADOConnectuion e sul pulsante di scatto anche Scrivo seguente codice quindi non ottengo alcun errore:Fondamentale di "Libero" a Delphi

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

Ma se creo lo stesso oggetto in fase di esecuzione, come follwos I ottenere "Violazione di accesso ..." errore

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

ottengo lo stesso errore anche se creo l'oggetto come di seguito:

ADOConnection := TADOConnection.create(nil); 

Proprio vorrei sapere il motivo dietro tale comportamento, vale a dire . perché non c'è errore quando tengo il componente in fase di progettazione?

+1

correlati: [perché non fa FreeAndNil * veramente * nil mio oggetto?] (http://stackoverflow.com/questions/8036388/delphi-why-doesnt-freeandnil-really-nil-my-object) – CodesInChaos

+0

Vishal, non è utile (in realtà è scoraggiato) per aggiungere formule educate alle tue domande e risposte qui su SO. – mghie

risposta

4

Se si libera un componente, il campo corrispondente nel proprietario viene cancellato. Se si aggiunge un design-time ADOConnection, poi

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

Potete vedere questo catturando in una variabile:

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

che non funzionano, anche quando ADOConnection viene creato in fase di progettazione.

Ecco un esempio con una componente TButton che dimostra come il comportamento che si vede per i componenti in fase di progettazione non è specifico per la progettazione di componenti in tempo:

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

Ultimo dubbio, perché questo comportamento per la progettazione cronometra ed esegue tempo ? –

+0

@VishalTiwari La differenza non è proprio tra tempo di progettazione e tempo di esecuzione, è tra proprietà e non possedute. Includerò un esempio in un po '. – hvd

+1

Il codice rilevante che imposta ADOConnection su nil è in TComponent.SetReference e non è direttamente correlato a Free, ma più a RemoveComponent (che è chiamato all'interno di Destroy). Questo meccanismo funziona quando il proprietario ha un campo chiamato come il componente figlio. –

3

ADOConnection è inizialmente nullo, quindi se lo si libera, la funzione gratuita non farà nulla perché il puntatore che ha consegnato è nullo. Il puntatore rimane nullo nelle chiamate successive, quindi continua a non fare nulla. Quando si inizializza ADOConnection con create, il puntatore contenuto in ADOConnection non è più nullo, quindi la prima chiamata a free libererà attivamente il puntatore, ma le chiamate successive vedranno che la memoria è già stata liberata e genererà un'eccezione. Il puntatore non viene modificato dalla chiamata a free. Per quello, avresti bisogno di freeandnil invece.

+0

Ma alcune volte la funzione FreeAndNil fornisce anche l'errore "Violazione di accesso ..." senza alcun motivo, ecco perché stavo lavorando con .Free –

+1

@VishalTiwari: hai effettivamente guardato il codice in FreeAndNil? Quella violazione di accesso proviene sicuramente da qualche parte, ma non vedo come potrebbe essere causato da FreeAndNil e non da Free ... –

+0

@VishalTiwari: quel tipo di riferimento non nullo non valido è chiamato * puntatore stantio *. A meno che il distruttore non sia scritto così male da generare un'eccezione AV non gestita, l'unico modo in cui mi ricordo di fare FreeAndNil genera un AV è quello di passare ad esso un puntatore scaduto .... –