2011-08-16 35 views
4

を解放するとき、私は、次のDelphiコードがあります:モジュールのアドレス4003AB4でアクセス違反TObjectListを

destructor TXX_XXXX.Destroy; 
var 
i: Integer; 
begin 
    if Assigned(Allocations) then 
    begin 
    for i:=0 to (Allocations.Count - 1) do 
    begin 
     try 
     TXX_ALOC(Allocations.Items[i]).Free; 
     except on Ex:Exception do 
     begin 
     OutputDebugString(PChar('Exception Error Message '+ Ex.Message)); 
     end; 
     end; 
    end; 

     // Above code works well - no exception 

     try 
    FreeAndNil(Allocations); {Exception Here} 
    except on E:Exception do 
    begin 
     OutputDebugString(PChar('Exception in xxxxxxxxx.pas'+E.Message)); 
    end; 
    end; 
    end; 
    inherited; 
end; 

アクセス違反 'Vcl50.bpl' を。アドレス2980BFFC

の読み取り、私は通常

  1. 無料
  2. は初期化せずに

をいくつかのオブジェクトを使用する。しかし、ここで私の前に前に解放されているいくつかのオブジェクトによって引き起こされる、アクセス違反を知っています私は割り当てが割り当てられていることを確認しました。私が例外処理を破棄すれば、私のアプリケーションは何か間違ったエラーをスローします。 配列は配列の場合はTObjectListです。配列に長さを割り当てなかったのは疑いがありますが、TObjectListです。

ありがとうございます!

+5

"しかし、ここで私が自由にする前に、割り当てが割り当てられていることを確認しました。"これは単に「フリー」を呼び出すだけでなく、明示的に 'nil'を参照してください(あるいは' FreeAndNil'を使うのが良いでしょう)。 'Free'は' nil'への参照を設定しません。それが 'Assigned'チェックです! – jpfollenius

答えて

18

TObjectListは、通常、その内容を破棄します。この場合、オブジェクトを解放しないでください。含まれているオブジェクトを再度解放しようとするため、TObjectListを解放すると、アクセス違反が発生します。あなたは自身その内容(手段のリストをしたい場合に指定し

使用この1:

オブジェクトリストのこの動作は、コンストラクタで制御することができる、それはアイテムを破壊するの面倒を見ますリストから削除されたとき、またはリストが破棄されたとき)。パラメータなしのコンストラクタ(おそらく使用している)は、これをtrueに設定します。

おそらくTListのようなリストを必要としますが、オブジェクトを格納するだけです。そのような場合は、次のようにリストを作成してください。

Allocations:= TObjectList.Create(False); 

しかし、自動破壊動作が必要な場合は、forループを削除してください。オブジェクトリストはあなたのTXX_ALOCオブジェクトを破壊します。

一般
7

、リストは、(それがデフォルトではない)オブジェクトを所有している場合、あなたが前にそれを解放しないでください、すなわち

for i := (Allocations.Count - 1) downto 0 do begin 
    Delete(Allocations.Items[i]); 
end 

しかしTObjectListの場合を開始するために、エンドからループにしたいリストをクリアリストがあなたのためにそれを行うように、コンテナを破壊する。上記のコードでは、リストがオブジェクトを所有している場合、Deleteを呼び出すとオブジェクトも解放されます。

+0

彼はそれを削除しないので、それほど重要ではありません。しかし、通常はあなたがします。 –

+1

リストの消去<>リストの要素を解放する – jpfollenius

+0

通常はyesです。しかし、より複雑な所有モデルが存在する場合、objを破棄すると、そのリストからobjを削除する可能性があります。そしてゼロに向かってループすることもやや最適です。だから、とにかくそれを使うのは良い考えです。しかし、ここで 'Delete'を使うようにサンプルコードを変更しました。 – ain

3

はあなたのための2つのオプション...

1)あなたは彼らがObjectListから削除されます際にDelphiが自動的にオブジェクトを解放したい場合はtrueに設定aOwnsObjects wiht TObjectListをを作成しています。あなたのデストラクタでは、単純なFreeAndNilはObjectList自体です。これにより、リストからすべてのオブジェクトが削除され、自動的に解放されます。

destructor TXX_XXXX.Destroy; 
begin 
    FreeAndNil(Allocations); // 
    inherited; 
end; 

2)あなたはの世話をする必要があります。その場合にはFalseに設定aOwnsObjects、wiht TObjectListを作成:自動的にそのリストに含まれるオブジェクトが解放されますObjectListを解放しているので、あなたのコードは、次にようになります。リスト内のオブジェクトを自由に解放します。あなたのコードは、次のようになります。

destructor TXX_XXXX.Destroy; 
var 
    i  : Integer; 
    oObject : TObject; 
begin 
    if Assigned(Allocations) then 
    begin 
    for i:= Pred(Allocations.Count) downto 0 do 
    begin 
     // Get a reference to the Object 
     oObject := TXX_ALOC(Allocations.Items[i]); 
     // Remove the object from the object list 
     Allocations.Delete(i); 
     // Free the Object 
     FreeAndNil(oObject); 
    end; 
    end; 

    FreeAndNil(Allocations); 
    inherited; 
end; 
+1

ループ内の 'FreeAndNil(oObject);'は、あなたがローカルのvarを除外しているため、「過剰」です。ちょうど 'oObject.Free'が行います。私はすぐにRudyがあなたに教えてくれると確信しています:) – ain

+0

ローカル変数でも 'FreeAndNil'を使うことはIMHOを害しませんし、毎回どの言語を使うかについて考える必要がないという利点があります。 – jpfollenius

+0

'Free'と' FreeAndNil'の議論についてはこちらを参照してください:http://stackoverflow.com/questions/3159376/which-is-preferable-free-or-freeandnil – jpfollenius