タブに貼り付けたクラスの破棄は?

解決


吉田  2009-05-20 23:51:03  No: 34470

よろしくお願いします。環境はWindowsXP sp3  Delphi 6 Personalです。
ただいま、下記のママんさんが後の方に書かれたタブブラウザを見本にタブブラウザを作成しています。
https://www.petitmonte.com/bbs/answers?question_id=4078
動的に作成するタブページのクラスを TIETabSheet = class(TTabSheet)の
constructor TIETabSheet.Create(AOwner: TComponent);
で作成されています。
質問はこのタブを削除するとき変数に代入して破棄されているようです。
//タブ削除  destructor TIETabSheet.Destroy;があるので
procedure TForm1.ClosePage(Index: Integer);
var
  IETab:TIETabSheet;
begin
  if Index<0 then exit;
  IETab := TIETabSheet(PCBrowser.Pages[Index]);
  IETab.Free;
end;

質問:これを次のようにしても見た目は削除破棄するようですが問題はないのでしょうか。
//タブ削除
procedure TForm1.ClosePage(Index: Integer);
//var
  //IETab:TIETabSheet;
begin
  //if Index<0 then exit;
  //IETab := TIETabSheet(PCBrowser.Pages[Index]);
  //IETab.Free;
  TIETabSheet(PCBrowser.Pages[Index]).Free;
end;
よろしくお願いします。


monaa  2009-05-21 00:48:59  No: 34471

元を知りませんが、ソースを見る限り問題ないです。
ただし、例外対策をその前にやらないといけませんよ。


吉田  2009-05-21 02:33:44  No: 34472

monaaさん、有り難うございます。
初心者が一番解りにくいのは、インスタンスの破棄という部分です。
コントロールに貼り付けたコントロールは元を破棄すれば
関連するコントロールも破棄してくれるという概念を持っているので
いつも心配です。
有り難うございました。


monaa  2009-05-21 11:36:14  No: 34473

WindowsのGUIコントロールは目で見てわかるオブジェクトですから、
親子関係も一目瞭然です。
親が子をしっかりサポートするので自動的に破棄も納得できます。
ですが、そもそもオブジェクトってのは別にWindowの様なGUIコントロールの
為に作られたものではないので、見た目のないオブジェクトというのもあります。
見た目が無いので、親子関係もあったり無かったりです。
そもそも、破棄という動作は明示的に行わなくてはなりませんが、
親が破棄されるとき子を破棄するのは自然な動作なので、他人が作った
大抵のオブジェクトはそういうコードが仕込まれてるってわけです。
そんなわけで、基本原則は自前で破棄になります。
ただ、VCLの様な他人の作ったオブジェクトでさらにGUIを備えてる場合は
確実に自動的に破棄されると思って構いません。
もちろん最大の親元であるアプリケーションを終了させれば、
特殊なメモリー操作さえしていなければ、すべてのオブジェクトは破棄されます。

ちなみにインスタンス1個に対してオブジェクト(ポインタ)複数
なんて場合もあります。
buttonA,buttonB,buttonC : TButton;
buttonA := TButton.Create;
としておいて
buttonB := buttonA;
buttonC := buttonA;
すればオブジェクト3個にインスタンス1個です。
buttonC.freeすればほかの二つはfree不要です。
こんなのが何の役に立つのか言われると、
そのうちわかるとしかいえませんが、この概念は結構重要です。
長々失礼しました。


だが  2009-05-21 17:17:31  No: 34474

> ちなみにインスタンス1個に対してオブジェクト(ポインタ)複数
> なんて場合もあります。
> (略)
> buttonC.freeすればほかの二つはfree不要です。

しかし、変数の値がnilになるわけではないので注意。

これは、結局全部Freeしにいこうとして、アクセス違反になる。
if buttonA <> nil then buttonA.Free;
if buttonB <> nil then buttonB.Free;
if buttonC <> nil then buttonC.Free;


Sam_Yasuyama  2009-05-23 21:24:39  No: 34475

> しかし、変数の値がnilになるわけではないので注意。

一般的には Create(AOwner: TComponent)の形で 初期化したものは Ownerが面倒を見てくれると思っています。 なので これを 破棄すると Ownerが 破棄しようとしたときに まずいことになりそうな気がします。(と 思って今やってみたら 別に大丈夫そうだったけど なんでだろ。 Desstroyのなかで Owner:=nilとでもしているのかな)

何らかの都合で Owner付きのコンポーネントを自分で破棄する場合は
FreeAndNil(buttonA);
( buttonA.free; buttonA := nil; でも良いかな?)
とすれば 安心な気がします。(場合にもよるのでしょうが)

破棄忘れによる リークを検出するの方法は
<a href="http://edn.embarcadero.com/article/33696"> edn </a> の記事が参考になります。


は?  2009-05-24 02:09:20  No: 34476

Owner は自分の所有してるコンポのリストを持ってる。コンポは自分が破棄される時、オーナーに申し出て、リストから削除してもらう。だからコードで破棄しても安心。

インスタンス変数が破棄後に自動的に nil にならないから FreeAndNil() 使うべき
とかとはまったく関係ない話ですよ。


Sam_Yasuyama  2009-05-24 20:32:03  No: 34477

解決済み問題を 混ぜ返して ごめんなさい。

> コンポは自分が破棄される時、オーナーに申し出て

これは こんな形で実装されているのではと思ったまでです。 
>Desstroyのなかで Owner:=nilとでも
property Owner: TComponent read FOwner write setOwner;
(邪推かなぁ 生成後にOwnerを変更することも少ないだろうけど
こうなっていそうな気がしたので)

ここまでが 最初の質問に対して 反射的に出てきた感想。
よく考えて見ると 別に質問内容とは関係ないですね。

で、FreeAndNil()のほうは 「だが」 さんの Resに対する脊髄反射と
前半の Ownerの話が 混ざってしまいました。
「Ownerつきの」の部分を 「他からも参照されていそうな」くらいに
読み替えてください。
まぁ結局 nilにしても nilになった変数のメソッドを 呼んだりしたら
駄目でしょうから 「使うべき」ではなくて「気分の問題」でしょうが。   

ということで 流してくださいませ。


Sam_Yasuyama  2009-05-24 20:46:56  No: 34478

連投ごめんなさい
>こうなっていそうな気がしたので

書き忘れました。 本当はこの部分
Ownerは 読み込み専用プロパティーで
Destroyの時には Ownerの RemoveComponent()
を 呼ぶという 「は?」 さんのおっしゃる通りに
なっていました。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加