2
procedure FreeListObjects( l : TStrings);
var i : integer;
BEGIN
   FOR i :=  0 TO l.Count -1 DO BEGIN
       l.Objects[i].Free;
       l.Objects[i] := NIL;
   END;
end;



PROCEDURE StringListAdd;
VAR i : INTEGER; Code : LONGWORD;
BEGIN
   l := Classes.TstringLIST.CREATE;
   FOR i := 0 TO 4 DO BEGIN
       Code := i  ;
       l.AddObject('', TObject(code));
   END;
   Code := LONGWORD(l.Objects[2]);
   FreeListObjects(l);
   l.Free;
END;

l.OwnsObjects := TRUE なし で使用FreeListObjects(l)するとエラーが発生します。

この文字列リストのオブジェクトを解放するのは誰ですか?

4

7 に答える 7

7

配列内のオブジェクトを所有していることを文字列リストに伝えましたObjects。その場合、リストを破棄すると、コードFreeと同じように、これらすべての値が自動的に呼び出されます。FreeListObjects

しかし、そこにはオブジェクトがありません!オブジェクトではない値を取得Integerし、それらを型キャストしてTObject. を呼び出すことはできませんがFreeIntegerコードが を呼び出す時点でFreeは、値の元の型はわかりません。型キャストを行うと、自分が何をしているのかを知っていることをコンパイラーに伝え、コンパイラーはあなたを信じます。自分が何をしているのかよくわからない場合は、型キャストしないでください。

なしでエラーが発生すると言いますが、 を使用してエラーが発生するFreeListObjectsはずです。問題は、オブジェクトではないものを呼び出していることです。独自のコードで呼び出すか、ライブラリに呼び出させるかは問題ではありません。 FreeListObjectsFree

C# を使用したことがあるかもしれません。その言語では、整数は自動的に「ボックス化」されて実際のオブジェクトになります。それは Win32 Delphi の仕組みではありません。Delphi はボックス化とアンボックス化を行いません。

于 2009-09-08T14:01:34.353 に答える
3

OwnsObjects は基本的に FreeObjects ルーチンと同じことを行いますが、StringList 自体が解放されるときに内部的に処理します。

しかし、あなたの問題はあなたの例から来ているように見えます。これを実行すると、保存している「オブジェクト」がオブジェクトではなく、TObject スロットに強制された整数であるため、アクセス違反が発生します。

これは単なる推測ですが、「すべてがオブジェクトである」他の言語のバックグラウンドを経て、Delphi を学んでいますか? Delphi ではそうではありません。オブジェクトは多くのデータ型のうちの 1 つであり、他のデータ型で Free を呼び出すことはできません。

于 2009-09-08T14:02:24.207 に答える
3

問題は、OwnObjects := true を設定すると、リストがその中のすべての項目に対して free を呼び出すためです。ただし、整数を TObject にキャストするだけで、実際には Integer 型のオブジェクトを作成していないため、このキャストされたオブジェクトでメソッドを呼び出すことはできません。

問題の解決策は、次のようなクラスを作成することです。

TInteger = class
  value: integer;
  constructor Create(v: integer);
end;

このクラスのインスタンスであるリスト項目を次のように置き換えて配置します。

   l.AddObject('', TObject(code));

   l.AddObject('', TInteger.Create(code));
于 2009-09-08T14:10:00.210 に答える
2

ロブの答えを拡張する:アドレスに関連付けられた何かを解放しようとしています:それぞれnil、0x00000001、0x00000002、0x00000003、および0x00000004。そこには有効なオブジェクトがないため、アクセス違反が発生します (注: nil オブジェクトで Free を呼び出してもエラーは発生しません)。

于 2009-09-08T14:05:25.847 に答える
0

他の人があなたのコードの問題をすでに指摘しているので、ちょっとした情報を追加します。リストに整数を格納するだけの場合は、GpListsユニットの TGpIntegerList または TGpInt64List を使用します。無料で、縛りはありません。

于 2009-09-09T08:14:17.967 に答える
0

Delphiでは、次のようにして各オブジェクトを解放する必要があることを知っています。

たとえば、オブジェクトが次のクラスの場合。

TheClass = Class(TObject)
public
thestr:String;
end;

次に、これはあなたがそれを行う方法です:

procedure FreeListObjects( l : TStrings);
var i : integer;
BEGIN
   FOR i :=  0 TO l.Count -1 DO BEGIN
       TheClass(l.Objects[i]).Free;   <----
       l.Objects[i] := NIL;
   END;
end;

オブジェクトへのポインタを解放している場合でも、TStrings リスト内のすべてのオブジェクトは、実際には独自のメモリ ロケーションに常駐しています。上記を実行して、オブジェクトのメモリを解放する必要があります。それが私がそれを行う方法であり、Delphiでそれを行いました。それはいつも私のために働いてきました。

于 2011-09-06T13:11:11.383 に答える
0

申し訳ありませんが、これはスタックオーバーフローで初めてです。次回は質問がより正確になります。l.addobject は tstringlist にオブジェクトを作成して追加すると思いました。l.addobject('', tobject(code)) (ここで、l は tstringlist で、code はロングワード) はメモリ リークを引き起こしますか? ロングワードはいつ配置されますか? 私はいつでもコードを取得できます:= Longword(L.objects[i]); タイプキャストしているオブジェクトは何ですか?

于 2009-09-09T12:35:05.660 に答える