2013-10-12 13 views
5

L'utilizzo dell'array dinamico in una variabile di classe per archiviare oggetti che devono essere liberati quando viene chiamato il distruttore di classe non funziona.Variabile di classe Delphi che esce dall'ambito prima che il distruttore di classe venga chiamato

La matrice sembra essere stata esclusa dall'ambito e già eliminata prima che venga chiamato il distruttore di classe. È questo in base alla progettazione?

Esempio testato in XE5:

type 
    TLeakingObject = class 
    public 
    I : Integer; 
    end; 

    TTheLeakOwner = class 
    public 
    class var OutofScopeArray:array of TLeakingObject; 
    procedure Add; 
    class destructor Destroy; 
    end; 

procedure TestThis; 
var LeakingTest : TTheLeakOwner; 
begin 
    LeakingTest := TTheLeakOwner.Create; 
    try 
    LeakingTest.Add; 
    finally 
    LeakingTest.DisposeOf; 
    end; 
end; 

{ TTheLeakOwner } 

procedure TTheLeakOwner.Add; 
begin 
    setlength(OutofScopeArray, length(OutofScopeArray) + 1); 
    OutofScopeArray[length(OutofScopeArray) - 1] := TLeakingObject.Create; 
end; 

class destructor TTheLeakOwner.Destroy; 
var I: Integer; 
begin 
    // Length(OutofScopeArray) always = 0, gone out of scope before class destructor ?? 
    for I := 0 to Length(OutofScopeArray) - 1 do 
    FreeAndNil(OutofScopeArray[i]); 
end; 
+0

Non una risposta, ma un consiglio: non usare array per oggetti, ma TObjectList (generics.collections), libererà gli oggetti per te quando l'elenco non rientra nello scope. – whosrdaddy

+0

Sì, lo so, ma questa perdita si verifica in una libreria di pool di thread open source, quindi volevo sapere se questo è come previsto dalla lingua prima di dare un'occhiata. – jong

+0

non c'è bisogno di preoccuparsi, i vars vengono puliti prima del distruttore di classe, vedere la mia risposta – whosrdaddy

risposta

5

Il distruttore classe viene chiamato DOPO unità finalizzazione quindi questo significa che la matrice non esiste al momento il distruttore classe si chiama. Alla finalizzazione dell'unità tutte le variabili gestite vengono ripulite dalla RTL. Alla fine non dovrebbe avere importanza perché non è una vera perdita.

Allen Bauer fornisce ulteriori informazioni sui costruttori/distruttori di classe here.

EDIT

A quanto pare questo è di design

+0

Grazie per queste informazioni, cambierò questo per essere un TObjectlist. – jong

1

Questo "progetto" è stato già fissato. Delphi 10 Seattle si comporta esattamente come tutti (compresi voi e me) - libera le variabili di classe conteggiate di riferimento dopo il distruttore di classe.

Probabilmente qualcuno da Embarcadero rese conto alla fine che il contrario non è assolutamente fresco, soprattutto con ARC su piattaforme mobili: D

See: https://quality.embarcadero.com/browse/RSP-11289

Problemi correlati