動的フレームの再作成でエラー

解決


ばにわ  2006-07-16 10:08:48  No: 22529

動的フレームの再作成でエラーが出て困っています。

具体的にはform1上のボタンでフレーム表示(動的作成)、
フレームには自身を消すためのボタンを配置。

この状態で1度開放したものを再表示させるとエラーが出ます。
回避するにはどうしたらよいのでしょうか?

var a:tframe2;//別ユニットで定義

form:

procedure TForm1.Button1Click(Sender: TObject);
begin
a:=tframe2.Create(self);
a.Top:=100;
a.Left:=100;
a.parent:=form1;
a.Show;
end;

frame:
procedure TFrame2.Button1Click(Sender: TObject);
begin
a.free;//freeでも同様にエラー
end;


はにわ  2006-07-16 10:10:23  No: 22530

登校されていないと思って再投稿してしまいました。
管理人様、削除願います。


Mr.XRAY  URL  2006-07-17 10:04:52  No: 22531

はにわさん。
提示のコードだと、フレーム関係の前に別のエラーが発生しませんか。
それと古い話ですが『実行すると・・・』という質問の結果はどうなりました?


はにわ  2006-07-23 04:29:34  No: 22532

時間が空いてしまいましたがレスありがとうございます。

>別のエラーが発生しませんか。

abstract エラーがまれに発生するようです。

>それと古い話ですが『実行すると・・・』という質問の結果はどうなりました?

それは別の方です。


Mr.XRAY  2006-07-30 01:23:05  No: 22533

(1) 新規にプロジェクトを作成
(2) [ファイル][フレームの新規作成]
(3) [Unit1]を編集対象にする
(4) [ファイル][ユニットを使用する]でunit2を選択
(5) ボタンを2つ配置する
(6) unit1.pasのコードを以下の通りとする

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

uses Unit2;

var  a: tframe2;

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
begin
     if not Assigned(a) then a:=tframe2.Create(self);
     a.Top:=100;
     a.Left:=100;
     a.parent:=form1;
     a.Show;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
     FreeAndNil(a);
end;

end.

これで確認してみて下さい。
動作確認は、WindowsXP(SP2) + Delphi5(UP1)です。 

>それは別の方です。
発言する前に確認するといいでしょう。レスをつける方の中にはその人が以前どんな
発言(質問)をしているかによって、レスの内容を考える場合があります。
(その人のスキルを判断するために)
発言に関する一般的な注意については、私のサイトにリンクがありますので、参考に
して下さい。


はにわ  2006-08-19 06:49:04  No: 22534

また時間が空きましたが・・・

上のコードは正常に動きました。(XPSP2 del7pro)

現在作成しているのはフレームが10個以上(すべて同サイズ)用意してあり、
フォーム上のリストボックスをクリックすると対応するフレームが
同じ位置に生成(すでに生成されていたら表示)

表題のコード通りですとabstractエラーがでたりするので
無理やりタイマーを使ってメインのunit1.pasからfreeするようにすると
エラーは出なくなったのですが効率が悪いので、フレーム上から自分自身を解放したいと思っています。

また生成・表示されたフレームを一番上に表示するのにもすでにあるフレームをすべてhideしていますが、この点も効率のよい方法ありませんか?


まさ  2006-08-19 09:43:22  No: 22535

すみません、技術不足せいか正しく質問が理解出来ませんでした^^;
とりあえず、書いてみましたが、違っていたらすみません。

まず、気になった点はモーダレスのフォームは、Releaseで必ず解放して下さい。
FreeAndNilで解放するフォームはモーダルの場合です。
あと、インスタンスを一つにしたい場合は、Singletonパターンを使った方が良いです。簡単なサンプルを書いてみました、参考にして下さい。

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

uses Unit2;

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
  a: TForm2;
begin
  a        := TForm2.GetInstance(Self);
  a.Top    := 100;
  a.Left   := 100;
  a.parent := Form1;
  a.Show;
end;

end.

unit Unit2;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm2 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
    class function  GetInstance(AOwner: TComponent): TForm2;
    destructor Destroy; override;
  end;

implementation

{$R *.dfm}

var
  Form2: TForm2;

procedure TForm2.Button1Click(Sender: TObject);
begin
  Release;
end;

destructor TForm2.Destroy;
begin
  Form2 := nil;
  inherited;
end;

class function TForm2.GetInstance(AOwner: TComponent): TForm2;
begin
  if not Assigned(Form2) then
  begin
    Form2 := TForm2.Create(AOwner);
  end;
  Result := Form2;
end;

end.


Frame  2006-08-20 02:11:55  No: 22536

>まず、気になった点はモーダレスのフォームは、Releaseで必ず解放して下さい。
>FreeAndNilで解放するフォームはモーダルの場合です。
モーダルだからとかモードレスだからという違いではないですね。
フォームのインスタンス中から自分を直接Freeすることは出来ません。
そのような用途のためにReleaseがあります。
そのフォームまたはその子フォームのイベントハンドラ以外からではFreeAndNilやFreeをすることは構いません。
ただ、質問者さんはフォームではなくフレームと仰ってますので(TFrameには)Releaseがありませんが・・・


まさ  2006-08-20 03:53:23  No: 22537

Frameさん、こんにちは
ご指摘ありがとうございます。フレームとフォームを勘違いしてますた。
ただ少し気になる点もあるので、質問させて下さい。

>モーダルだからとかモードレスだからという違いではないですね。
>フォームのインスタンス中から自分を直接Freeすることは出来ません。
>そのような用途のためにReleaseがあります。
>そのフォームまたはその子フォームのイベントハンドラ以外からではFreeAndNilやFreeをすることは構いません。

Releaseの用途について、このように書かれていますがDelphi7のReleaseのヘルプでは

>メモ:        フォームを安全に破棄するには,Release メソッドだけを使用してください。Free メソッド(Delphi)または delete キーワード(C++)を使用しないでください。

と書かれていますよね。これだけを読むとフォームを破棄する時には
Free(FreeAndNil)を使ってはいけないと読めます。

まちろん、フォームを破棄するのに、Free(FreeAndNil)を使っても
大丈夫な場合もありますが、その基準は

・画面が実行中(内部コードがフォームのオブジェクトを参照する可能性があるもの):Release
・画面が閉じたもの(内部コードがフォームのオブジェクトを参照しないもの):Free(FreeAndNil)
(すみません、この辺りの考え方を単純にモーダル・モードレスと書いてしまいました、厳密には違いますが...^^;)

だと思います。このようにしないとFree直後に内部コードがフォームオブジェクトを
参照してアクセス違反が起きる可能性があるます。

Frameさんの
>そのフォームまたはその子フォームのイベントハンドラ以外からではFreeAndNilやFreeをすることは構いません。

では、モーダレス場合ではアクセス違反が起きませんか?


Frame  2006-08-20 05:01:04  No: 22538

>と書かれていますよね。これだけを読むとフォームを破棄する時には
>Free(FreeAndNil)を使ってはいけないと読めます。
Releaseのソースを見ていただけたら分かると思いますが、Releaseではメッセージを自分のWindowに投げてリターンしているだけです。(まだ実体は存在している)
実際の解放はメッセージのアイドルループの処理の中で行うようになっています。
そこでの解放にはFreeを使用しています。
このことからもFree/FreeAndNilを使用することには全く問題がないことが分かると思います。
Free/FreeAndNilを実行するタイミングが問題なのです。
よって
モーダル/モードレスとは関係はありません。


Frame  2006-08-20 05:14:03  No: 22539

追伸)
Delphi7のヘルプには「フォームまたはその子フォームのイベントハンドラでは」 Free (Delphi) または delete (C++) のかわりに Release を使う必要があります。
と「イベントハンドラの中では」という記述がありあます。
又、
Releaseを行えば安全かというと必ずしもそうではない場合があります。
例えば var frm2: TForm2; 等としてReleaseを実行して解放した後でも
frm2は以前存在しているオブジェクトとのアドレスを保持しています。
よってアプリ側では frm2にnilを代入しておく等しておかないと誤ったアクセスを起こす可能性があります。


まさ  2006-08-20 08:33:07  No: 22540

Frameさん、こんばんは、すみませんが回答がよく分かりません。
具体的に、Showで表示したフォームを、
>そのフォームまたはその子フォームのイベントハンドラ以外からではFreeAndNilやFreeをする
のサンプルソースがあると助かります。m(__)m

私が思うには、結局
>このことからもFree/FreeAndNilを使用することには全く問題がないことが分かると思います。
>Free/FreeAndNilを実行するタイミングが問題なのです。
タイミングの問題ですよね、だからそれを回避するために、Delphi標準のReleaseを使うと思うんですが?
もちろん、似たような構造で作れば可能だと思いますが...(それなら標準で?)

あと、
>モーダル/モードレスとは関係はありません。

私の書き方が悪かったのかもしれませんが、私の考えは
>>・画面が実行中(内部コードがフォームのオブジェクトを参照する可能性があるもの):Release
>>・画面が閉じたもの(内部コードがフォームのオブジェクトを参照しないもの):Free(FreeAndNil)
>>(すみません、この辺りの考え方を単純にモーダル・モードレスと書いてしまいました、厳密には違いますが...^^;)
だと思います。たしかに厳密には「タイミングの問題」だと思いますが、別フォームから見た場合
  ・モーダルは、確実に終了が分かる。
  ・モードレスは、内部コードがオブジェクトを参照している可能性が常にある。
よって、モーダル/モードレスでFreeAndNilとReleaseを使い分けています。
もちろん、モードレスでもスレッドや非同期などの処理が行われなければ可能性は低いと思いますが
それでも必ずないとはいえません。だからモーダレスは必ずReleaseで解放していました。

でも次回からは、Frameさんにお願いした、モーダレスを安全に解放するソースを参考にさせてもらいたいので
是非サンプルソースを宜しくお願い致します。m(__)m


Frame  2006-08-20 12:51:59  No: 22541

どうもモーダル/モードレスの意味が違うような気がしますが。
http://e-words.jp/w/E383A2E383BCE38380E383ABE38380E382A4E382A2E383ADE382B0.html

Freeするタイミングの問題はSendMessageとPostMessageの処理の違いに起因するものです。
内容がこのスレと違う方向にいっているようですのでこれ以上掘り下げませんが


まさ  2006-08-20 21:59:04  No: 22542

Frameさん、こんにちは。遅い時間の返信ありがとうございます。

>どうもモーダル/モードレスの意味が違うような気がしますが。
私の認識しているモーダル/モードレスの意味は、簡単に説明するとフォームを
Showで表示するとモードレスで、ShowModalで表示するのがモーダルと思っています。
意味は違っていないと思いますよ。

あと、ヘルプなんですが
>Delphi7のヘルプには「フォームまたはその子フォームのイベントハンドラでは」 Free (Delphi) または delete (C++) のかわりに Release を使う必要があります。
>と「イベントハンドラの中では」という記述がありあます。
と確かに書いてありますよね、「フォームまたはその子フォームのイベントハンドラでは」は
「説明」に書かれていますが、これが「メモ」にもかかってくるのでしょうか?
また「フォームまたはその子フォームのイベントハンドラでは」も私のサンプルで
>procedure TForm1.Button1Click(Sender: TObject);
>var
>  a: TForm2;
>begin
>  a        := TForm2.GetInstance(Self);
>  a.Top    := 100;
>  a.Left   := 100;
>  a.parent := Form1;
>  a.Show;
>end;
と書いていますが、Frameさんの発言は

>このことからもFree/FreeAndNilを使用することには全く問題がないことが分かると思います。

と書いていますよね。
これは「フォームまたはその子フォームのイベントハンドラでは,Release メソッドを使う必要があります。」が
  ・フォームのイベントハンドラでフォームを破棄    :Release
  ・子フォームのイベントハンドラで子フォームを破棄:Release
  ・フォームのイベントハンドラから子フォームを破棄:FreeAndNil
  ・子フォームのイベントハンドラからフォームを破棄:FreeAndNil
と言う事ですか?

>内容がこのスレと違う方向にいっているようですのでこれ以上掘り下げませんが
そうですね。私も私の勘違いが始まりなので申し訳ないと思っていました。m(__)m
(Frameさんのサンプルソースを読みたかったのですが^^; )


Frame  2006-08-21 01:07:44  No: 22543

>>内容がこのスレと違う方向・・・
なのですが、ちょっとだけ
一般的なイベントハンドラはSendMessageが起動元になっている場合が多いと思います。
これはいわゆる割り込みに近いもので他の処理をペンディングしてメッセージの処理をしています。その(割り込み)処理の中でFreeされてしまうとペンディングされている処理が再開された時にオブジェクトがなくなっているのでメモリ保護違反が起きる可能性が高くなります。
またPostMessageによるアイドルループでのメッセージイベントハンドラでは安全にFreeをすることが可能です。(ちゃんと設計されてれば)
(モードレス/モーダルとは直接関係ありません)
質問者さんの例にあるようにフレームのイベントハンドラからそのフレームをFreeするようなことは避けなければなりません。
フレームのイベントハンドラから自分を解放したければその親のフォームに何らかのメッセージをポスト(重要)して親に解放してもらう様な仕様が良いと思います。


はにわ  2006-08-21 05:46:53  No: 22544

まささんのコードでもいろいろやってみましたがやはりreleaseがフレームではないため回避できませんでした。

Frameさんの
>親のフォームに何らかのメッセージをポスト(重要)して親に解放してもらう様な仕様

具体的にどのような方法がありますか?
参考になるURLなどがあれば助かるのですが・・・


Frame  2006-08-21 07:50:26  No: 22545

例えばFormと同じようにTFrameにReleaseFrameを追加すると
----------------------------------------------
const
  CM_RELEASEFRAME = WM_APP+1;
type
  TFrame2 = class(TFrame)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    procedure CMReleaseFrame(var Message: TMessage); message CM_RELEASEFRAME;
    procedure ReleaseFrame;
 ・・・・
 end;

implementation

procedure TFrame2.CMReleaseFrame(var Message: TMessage);
begin
  Free;
end;

procedure TFrame2.ReleaseFrame;
begin
  PostMessage(Handle, CM_RELEASEFRAME, 0, 0);
end;

procedure TFrame2.Button1Click(Sender: TObject);
begin
  ReleaseFrame;  //  Freeではだめ
end;
----------------------------------------------
ここでは簡単に説明するため親ではなく自分にポストしました。
ただ、例えば frm2:=TFrame2.Create(Self) としてfrm2を動的に作成した後、frm2を上記の様に解放しても frm2は以前の参照が残されたままなのでそのまま再度frm2をアクセスすると当然エラーとなります。
これを避けるには上記でFreeをする時に参照している変数(frm2)もnilに設定すべきですがソフトによって参照箇所が一箇所とは限りません。
(参照の変数が固定されている時は直接nilを代入しても良いですが、キレイではないですね)
TFrameの場合は親が存在するわけですから親側にて処理すべきと思います。
親にポストするときは WPARAMかLPARAMでフレームのアドレス(参照)等を渡せばよいと思います。


Frame  2006-08-21 08:06:43  No: 22546

上記の方法+親でTFrameの解放を検出する方法
--------------------------------------
type
  TForm1 = class(TForm)
  ・・・・
  protected
    procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  ・・・・
  end;

implementation

var frm2: TFrame2;

procedure TForm1.Notification(AComponent: TComponent;
  Operation: TOperation);
begin
  inherited;
  if (Operation = opRemove) and (AComponent = frm2) then
    frm2 := nil;
end;
--------------------------------------
Form1上にTFrame2を作成した場合


Frame  2006-08-21 08:56:42  No: 22547

念のため)
わざわざ frm2 := nil; としているのは
if Assigned(frm2) then ・・・
として判断できるようにするためです。
Freeしただけでは Assigned(frm2) で有効か無効かの判定が出来ません。
DelphiのAssigned(・・・)  は単に nilかどうかをチェックしているだけです。


まさ  2006-08-22 01:31:10  No: 22548

はにわ(ばにわ?)さんへ
私も話しを脱線させたので、お詫びにSingletonパターン版を書いて見ました。
>また生成・表示されたフレームを一番上に表示するのにもすでにあるフレームをすべてhideしていますが、この点も効率のよい方法ありませんか?
上記もBringToFrontメソッドを使ってみました。

追伸
  Frameさん、TObject.Freeヘルプの最後にもに
>フォームを解放するには,Release メソッドを使います。Release メソッドは,すべてのイベントハンドラと,含まれているコンポーネントが実行を完了した後で,フォームを破棄し,フォームに割り当てられていたメモリを解放します。
と書かれています。それでもフォームをFree(FreeAndNil)で破棄するんですか?
こんなこと常識だと思っていますたが・・・・(-_-;)

はにわさん、長くしてしまってすみませんでした。もうこれ以上フォームの話はしません。m(__)m

--------------------------------------------------------------------------------
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private 宣言 }
  protected
    { protected 宣言 }
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

uses Unit2, Unit3;

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
begin
  TFrame2.GetInstance(self, 100, 100);
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  TFrame3.GetInstance(self, 100, 300);
end;

end.

--------------------------------------------------------------------------------
unit Unit2;

interface

uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, Unit1;

type
  TFrame2 = class(TFrame)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private 宣言 }
    procedure CMRelease(var Message); message CM_Release;
  protected
    { protected 宣言 }
  public
    { Public 宣言 }
    class function  GetInstance(AOwner: TComponent;ATop,ALeft: Integer): TFrame2;
    destructor Destroy; override;
  end;

implementation

{$R *.DFM}

var
  Singleton: TFrame2;

procedure TFrame2.Button1Click(Sender: TObject);
begin
  PostMessage(Handle, CM_RELEASE, 0, 0);
end;

class function TFrame2.GetInstance(AOwner: TComponent;ATop,ALeft: Integer): TFrame2;
begin
  if not Assigned(Singleton) then
  begin
    Singleton      := TFrame2.Create(AOwner);
  end;
  Singleton.Top    := ATop;
  Singleton.Left   := ALeft;
  Singleton.parent := TForm(AOwner);
  Singleton.Show;
  Singleton.BringToFront;
  Result := Singleton;
end;

destructor TFrame2.Destroy;
begin
  inherited;
  Singleton := nil;
end;

procedure TFrame2.CMRelease(var Message);
begin
  Free;
end;

end.

--------------------------------------------------------------------------------
unit Unit3;

interface

uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, Unit1;

type
  TFrame3 = class(TFrame)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private 宣言 }
    procedure CMRelease(var Message); message CM_Release;
  public
    { Public 宣言 }
    class function  GetInstance(AOwner: TComponent;ATop,ALeft: Integer): TFrame3;
    destructor Destroy; override;
  end;

implementation

{$R *.DFM}

var
  Singleton: TFrame3;

procedure TFrame3.Button1Click(Sender: TObject);
begin
  PostMessage(Handle, CM_RELEASE, 0, 0);
end;

class function TFrame3.GetInstance(AOwner: TComponent;
  ATop,ALeft: Integer): TFrame3;
begin
  if not Assigned(Singleton) then
  begin
    Singleton      := TFrame3.Create(AOwner);
  end;
  Singleton.Top    := ATop;
  Singleton.Left   := ALeft;
  Singleton.parent := TForm(AOwner);
  Singleton.Show;
  Singleton.BringToFront;
  Result := Singleton;
end;

destructor TFrame3.Destroy;
begin
  inherited;
  Singleton := nil;
end;

procedure TFrame3.CMRelease(var Message);
begin
  Free;
end;

end.


えーと  2006-08-22 03:22:12  No: 22549

> それでもフォームをFree(FreeAndNil)で破棄するんですか?

Release は、たんに非同期開放を行うだけです。Frame さんも書かれているようにPostMessage() を使って、いったんハンドラを出たあと開放します。この仕組みさえ
分かっていれば、Release() を使う必要がない場面もすぐに分かります。その場合は
Free や FreeAndNil() を使っても一向に構いません。


Frame  2006-08-22 04:20:23  No: 22550

まさ さんへ
>それでもフォームをFree(FreeAndNil)で破棄するんですか?
>こんなこと常識だと思っていますたが・・・・(-_-;)
えーとさんの書かれていることがすべてです
Releaseの行き着く先はFreeなのです。
貴方の常識に基づく前にDelphiのVCLのソースを読んでみてください。


まさ  2006-08-23 01:56:06  No: 22551

えーとさん、Frameさん  こんにちは
えーとさんも参加されたので、もう一度発言します。

まず、議論の仕方ですが、このような技術的な話は
客観的に議論しないと、と私は思っています。
その為、私は正式な文献を引用して発言してきました。
しかし、えーとさんとFrameさんは、主観的な回答をしていますよね
これでは、議論が噛み合いません。
Delphiのヘルプで書かれていることが信用してもらえない状況では
どう説明すれば分かって貰えるか分かりません。
(これからは、これを見ている他の人為に書くつもりです)

>Releaseの行き着く先はFreeなのです。
>貴方の常識に基づく前にDelphiのVCLのソースを読んでみてください。
これもソースは客観的な物なので皆さんが分かると思いますが
しかしFreeを使っても大丈夫だと言う理由が客観的に示されていません。
Freeを使っても大丈夫だと思うのはFrameさんの主観なのです。
私がソースを読んでFreeを使ってはいけないと思いました。
これが私の主観です。

一回私の考えを全て書いてみます。
(主観ですから、正しいとはかぎりません。参考程度で)
Frameさんがよく発言されている。PostMessage・SendMessageの件ですが
私の認識では、PostMessageはキュー(スレッド毎)に貯めた順番に実行され、
SendMessageは先入れ先出し(FIFO)で実行されます。
つまり、別フォームをFreeする場合、Free先のキューにPostMessage処理がある場合
それより先にFreeが実行され、その後にPostMessage処理が実行され
エラーになる可能性があるます。
Frameさんは、
>Releaseのソースを見ていただけたら分かると思いますが、Releaseではメッセージを自分のWindowに投げてリターンしているだけです。(まだ実体は存在している)
>実際の解放はメッセージのアイドルループの処理の中で行うようになっています。
>そこでの解放にはFreeを使用しています。
>このことからもFree/FreeAndNilを使用することには全く問題がないことが分かると思います。
と思っているようですが、私の考えでは
>「Windowに投げてリターンしているだけ」
が重要だと思います。これにより安全に解放されると思っていますし
それが出来ないFreeは「使ってはいけない」と思います。

次に
>一般的なイベントハンドラはSendMessageが起動元になっている場合が多いと思います。
>これはいわゆる割り込みに近いもので他の処理をペンディングしてメッセージの処理をしています。その(割り込み)処理の中でFreeされてしまうとペンディングされている処理が再開された時にオブジェクトがなくなっているのでメモリ保護違反が起きる可能性が高くなります。
>またPostMessageによるアイドルループでのメッセージイベントハンドラでは安全にFreeをすることが可能です。(ちゃんと設計されてれば)
この発言の「PostMessageによるアイドルループでのメッセージイベントハンドラでは安全にFreeをすることが可能」と考えているようですが
(上での発言「Free/FreeAndNilを使用することには全く問題がない」よりは、少しは
  分かってもらえたみたいですが、あとすこし分かってもらえると...)
PostMessage処理は、自フォーム内でのイベント場合ですか?
その場合、自フォームのキューで待機するだけです。相手フォームを安全にFreeすることが出来ません。
Freeする相手フォームでのイベントの場合、もちろん上手くいきます
それが、Releaseと同じ構造だからです。

もちろん、えーとさんの
>Release は、たんに非同期開放を行うだけです。Frame さんも書かれているようにPostMessage() を使って、いったんハンドラを出たあと開放します。この仕組みさえ
>分かっていれば、Release() を使う必要がない場面もすぐに分かります。その場合は
>Free や FreeAndNil() を使っても一向に構いません。
言うとおり、Freeを使って絶対に問題が出るとは私にも言えません。
しかし、絶対に問題がないとも言えないのです。
>「Release() を使う必要がない場面もすぐに分かります」
と発言されていますよね、すぐに分かりますか?
私の考えではFreeを使って良い場合は、PostMessageメッセージが使われていないか
またはFreeが実行される前に全てのPostMessage処理が実行を終了していることを
保証しないといけません。
この事を、フォーム自身・他フォーム・VCLなどからの実行される、
全てのPostMessage処理についも保証しないといけません。
(もちろん同じ(フォーム自身)キューで実行される処理の話です)
ましてや、ユーザーがどのような操作をしても、また環境や他のアプリの影響で
キューの実行が遅延しても保証しないといけません。
これは、私には簡単には出来ません。もちろん、私より優秀な人は
簡単に出来と主張するかも知れませんが...
(そもそも、そんなに優秀な人はクラス設計時にクラスが別クラスの構造に
  依存しないように作ると思います。
  カプセル化はオブジェクト設計の基本なので...
  今回は技術的な話なので、設計の話は止めておきますが)

長くなったのでこれで終わります。


まさ  2006-08-23 02:24:55  No: 22552

これを読まれているみなさんへ実際どのような時に
エラーが起きるのか、確認してもらう為に
簡単なサンプルを載せておきます。

処理内容:
  ToolBarのToolButtonをクリックしたタイミングで
  別フォームからFreeAndNilをします。
  この時、VCLがPostMessageを発行しているので
  エラーが発生します。

--------------------------------------------------------------------------------
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private 宣言 }
    procedure Form2Free();
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

uses Unit2;

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
begin
  Form2 := TForm2.CreateAndSetEvent(Self, Form1.Form2Free);
end;

procedure TForm1.Form2Free;
begin
  FreeAndNil(Form2);
end;

end.
--------------------------------------------------------------------------------
unit Unit2;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ComCtrls, ToolWin;

type

  TForm2FreeEvent = procedure() of object;
  TForm2 = class(TForm)
    ToolBar1: TToolBar;
    ToolButton1: TToolButton;
    procedure ToolButton1Click(Sender: TObject);
  private
    { Private 宣言 }
      FormFree: TForm2FreeEvent;
  public
    { Public 宣言 }
    constructor CreateAndSetEvent(AOwner: TComponent;FreeEvent: TForm2FreeEvent);
  end;

var
  Form2: TForm2;

implementation

{$R *.DFM}

{ TForm2 }

{ TForm2 }

constructor TForm2.CreateAndSetEvent(AOwner: TComponent;
  FreeEvent: TForm2FreeEvent);
begin
  inherited Create(AOwner);
  FormFree := FreeEvent;
  Show;
end;

procedure TForm2.ToolButton1Click(Sender: TObject);
begin
  FormFree();
end;

end.


うらない  2006-08-23 02:30:28  No: 22553

> 別フォームからFreeAndNilをします。
これは、別フォームのメソッドとしてFormをFreeしていますが、
Form2でマウスダウンメッセージを処理している途中にすぎない。
したがって、Form2が自分自身をFreeしようとしていると、なんらかわりがない。
だからエラーになる。


うらない  2006-08-23 02:31:16  No: 22554

間違い

> これは、別フォームのメソッドとしてFormをFreeしていますが、
これは、別フォームのメソッドとしてForm2をFreeしていますが、


うらない  2006-08-23 02:36:32  No: 22555

連レスしまくり失礼

FreeAndNil(Form2);  が処理された後、
TForm2.ToolButton1Click(Sender: TObject);において、FormFreeの次の行・・・
まぁ、End; しかありませんが・・・に戻りますが、FreeAndNilで、メモリが破棄されている。
存在がなくなったところに戻ってアクセス違反。

別にPsotMessageとは関係ない。


オケ  2006-08-23 02:52:15  No: 22556

まさやんイタすぎ
まあ、理解が出来ていないからこんな投稿ばかりするのだろうけどアラシに近いヨ


とんこつ  2006-08-23 06:07:43  No: 22557

匿名でスマンです。
トラブル御免なので。あと私はスレッドの初めの方を読んでません。
面倒なので。

> その為、私は正式な文献を引用して発言してきました。
> しかし、えーとさんとFrameさんは、主観的な回答をしていますよね
> これでは、議論が噛み合いません。
> Delphiのヘルプで書かれていることが信用してもらえない状況では
> どう説明すれば分かって貰えるか分かりません。

Delphiのヘルプは誤りが多々あります。
そもそも日本人が訳してないといううわさもあります。
ボーランドの公式情報ではありますが、ヘルプは文献と呼べるほどの物ではありません、大目に見てもガイドにすぎないものです。
過去の投稿も含め、書き込みを見た感じでは、上の二方はVCLライブラリが読み、その多くを理解できています。
VCLライブラリこそ直接コンパイルされる原本なので、このライブラリに書かれていることこそが本質です。
もちろん日本語でも英語でもなくDelphi語です。
で、プログラミングや数学において”絶対”は存在します。
しっかり言語を理解してライブラリを読めば答えは一つしかありません。

今回の場合、単にまささんの勉強不足としか言いようがありません。
しかし、それをどうすれば理解させてあげられる事ができるかと言われると、所詮はBBS。
もっとちゃんとVCLが読めるようになればそのうち分かるとしか言えません。
もう少しです、がんばってちょ。


とんこつ  2006-08-23 06:31:38  No: 22558

ちょっとくらいコピペしても問題ないでしょう…
unit Forms;

procedure TCustomForm.Release;
begin
  PostMessage(Handle, CM_RELEASE, 0, 0);
end;

procedure TCustomForm.CMRelease;
begin
  Free;
end;


しょうゆ  2006-08-23 07:47:52  No: 22559

まさやんの認識間違いはこの辺にもあるよ
>私の認識では、PostMessageはキュー(スレッド毎)に貯めた順番に実行され、
>SendMessageは先入れ先出し(FIFO)で実行されます。
FIFOとはキューのことだよね
次のホームページで勉強してね
http://yokohama.cool.ne.jp/chokuto/urawaza/sendmsg.html
速く中級プログラマーを卒業して上級者の仲間入りを果たしましょう。


先入れ先出し  2006-08-23 16:56:11  No: 22560

つっこみ(^_^;)
細かいことは無視して
>私の認識では、PostMessageは貯めた順番に実行され、
>SendMessageは先入れ先出しで実行されます。
これでは、同じ意味になってしまいます。


メス  2006-08-23 22:21:15  No: 22561

あんまり突っ込むのもかわいそうだけど、まささんの勉強のために
>私の考えではFreeを使って良い場合は、PostMessageメッセージが使われていないか
>またはFreeが実行される前に全てのPostMessage処理が実行を終了していることを
>保証しないといけません。
PostMessage/SendMessageの違いが理解できていませんね。
FreeするときにPostMessageのメッセージがキューに貯まっていても無視しても構いません。


オス  2006-08-23 22:30:37  No: 22562

>客観的に議論しないと、と私は思っています。
>その為、私は正式な文献を引用して発言してきました。
>しかし、えーとさんとFrameさんは、主観的な回答をしていますよね
>これでは、議論が噛み合いません。
どう見てもまささんの方が主観的な発言のようですけど。


まさ  2006-08-24 00:42:50  No: 22563

Frame・えーと・うらない・オケ・とんこつ・しょうゆ・先入れ先出し・メス・オスさん、こんにちは

しょうゆさん、先入れ先出しさん
>私の認識では、PostMessageはキュー(スレッド毎)に貯めた順番に実行され、
>SendMessageは先入れ先出し(FIFO)で実行されます。
すみなせん。FIFOはPostMessageですね。
日本語の意味はあっていますよね?

すみません。サンプルも説明が間違っていました。
>この時、VCLがPostMessageを発行しているので
「この時、VCLがPostMessageを受信しているので」
です。
(誤字・間違いが多くてすみません、だから分かってもらえない?)

うらないさん、具体的な指摘ありがとうございます。
具体的なので反論しやすい、うらないさんに
反論させてもらいます。m(__)m                                       

うらないさんの考え方には、3つの間違いがあります。
ヒントを書くので自分で考えて下さい。

間違い1:ヒント
  うらないさんの考えでは、全てのボタンコンポーネントでもエラーになりますよね
  ここではTToolBarを使っていますが、これをTButtonに変えたらどうなりますか?
  (TToolBarは、削除して下さい)

間違い2:ヒント(と言うより答えですが理由を考えて下さい)
>TForm2.ToolButton1Click(Sender: TObject);において、FormFreeの次の行・・・
>まぁ、End; しかありませんが・・・に戻りますが、FreeAndNilで、メモリが破棄されている。
>存在がなくなったところに戻ってアクセス違反。
  procedure TForm2.Button1Click(Sender: TObject);
  begin
    FormFree();
    Form1.Caption := 'TEST';
  end;
  間違い1で修正したプログラムにFormFree()の後の処理を
  追加して下さい。FreeAndNilが実行された後の処理は
  実行されませんか?
  Form2は廃棄されましたがメソッドは生きています。
  この理由は、Delphiの内部構造を理解していないと
  分からない事なので、分からなくても大丈夫だと思いますが
  勉強の為に考えて下さい。

間違い3:ヒント
  秘密です。これは自分で考えて下さい。
  私が認識しているのが3つと言うだけで
  もっとあるかもしれません。
  がんばって下さい。

「間違い1」が分かってもらえれば、別フォームからのフォームFreeが
難しいのが分かってもらえると思いますが...
具体的に説明しても、皆さんが自分の考えを変える
つもりは、ないみたいなので止めます。

でも、なんでFreeにこだわるですか?
いままで、自分が書いたプログラムが
バグだと思うのがいやなんでしょうか?
Releaseも問題は若干ありますが、Freeより
安全だとおもいます。
(実話は私も直接Releaseを使いません(Freeも使いません)
  もっと安全な方法でやっていますが(~_~;))

スレが荒れたので、これで本当に最後にしますが
回答は優秀な人?が多いようなので、まかせます。
(皆さんが言われる通り、ソースを読めば分かりますが
 読む人のスキルで...皆さんもがんばって下さい)


あきれた  2006-08-24 01:07:15  No: 22564

自分の間違いに気付こうともしないようですね、この人は
能力の低い人なんだろうな?


いくらなんでも  2006-08-24 01:16:13  No: 22565

>Form2は廃棄されましたがメソッドは生きています。
おいおい


無担保無保証?  2006-08-24 01:55:59  No: 22566

>Form2は廃棄されましたがメソッドは生きています。
ううむ、Form2のメソッドが書かれたメモリ領域を解放した後でも、そこがクリアされていなければ、解放後にそこにアクセスしても一応正常がごときに実行されるかもしれないけど、解放したそこが他のアプリケーションによって確保/書き換えられてしまうことは考えられるので、そこへの正常アクセスはいつまでも保証されないのでは?


笑うセールスマン  2006-08-24 02:04:07  No: 22567

>Form2は廃棄されましたがメソッドは生きています。
仮にバイト単位でメモリ保護のできるシステムであったならば確実にメモリ保護エラーが出ますよね。

>この理由は、Delphiの内部構造を理解していないと
>分からない事なので、分からなくても大丈夫だと思いますが
Delphiとは関係ないし、Delphiを隅々まで理解しているような言動には笑わずにはいられません。


まさ  2006-08-24 02:48:58  No: 22568

「間違い2」に来ますか(笑い)
本当は、「間違い1」を考えて貰いたいので
本当に最後の一回ヒントを出します。

下に、例ではTTestをCreateしないで使っています。
Create/Freeは実際内部的に何をしているか、です。

無担保無保証?さん
>したそこが他のアプリケーションによって確保/書き換えられてしまうことは考えられるので、そこへの正常アクセスはいつまでも保証されないのでは?
エリア確保前に使えていますよね、後は自分で考えて下さい。

笑うセールスマンさん
>Delphiとは関係ないし、Delphiを隅々まで理解しているような言動には笑わずにはいられません。
Delphiとは関係ないですか、私は笑いません、がんばって下さい。

出来れば「間違い1」を考えて下さい。

--------------------------------------------------------------------------------
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

  TTest = class
  private
    { Private 宣言 }
  public
    { Public 宣言 }
    procedure Test();
  end;

var
  Form1: TForm1;
   Test: TTest;

implementation

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
begin
  Test.Test();
end;

{ TTest }

procedure TTest.Test();
begin
  Form1.Caption := 'AAA';
end;

end.


あーあ  2006-08-24 03:03:35  No: 22569

ここまでひどいとは・・・
居直ってるし・・・
もう何言っても間違いに気付かないよな


しかし  2006-08-24 03:18:26  No: 22570

話がすりかわっていますよね
最初の
>まず、気になった点はモーダレスのフォームは、Releaseで必ず解放して下さい。
>FreeAndNilで解放するフォームはモーダルの場合です。
から何でこうなるんだろう?
次から次に間違いを提供してくださるし・・・もういいや


おもてない  2006-08-24 04:22:55  No: 22571

> Frame 2006/08/20(日) 16:07:44 
> 一般的なイベントハンドラはSendMessageが起動元になっている場合が多いと思います。
> これはいわゆる割り込みに近いもので他の処理をペンディングしてメッセージの処理をしています。その(割り込み)処理の中でFreeされてしまうとペンディングされている処理が再開された時にオブジェクトがなくなっているのでメモリ保護違反が起きる可能性が高くなります。

だから、これがすべてじゃない?

別に、FormFree() の後で、すぐにアクセス違反になるとは書いてない
・・・が、まぁ、「なくなった領域に戻ってきたら」と思われてもしゃーないな。

メソッドなんて、所詮動作を記述したエリアへのポインタ?でしかないから、
クリエイトしていないクラスのメソッドで、自分の確保すべきメモリにさえ
アクセスしなければいい。
普通は class procedure 〜 と「class」を頭につけるけどな。

だから、FormFree を実行しているToolButton1Click自身は安全。
でも、それを実際に実行しているVCL内部は、必ずしも安全とは言えない。
Createしたときに確保されるメモリ領域にアクセスするかしないかは、
VCLの作り次第。
いくらメソッドがポインタであっても、そこが保証されない。

だから、Releaseを使い破棄するタイミングをずらし、フォーム上に乗っかっているその他VCL内部の影響を極力避ける。

今回のFormFreeメソッドは、他のフォームのメソッドを使っているだけで、
普通にFreeと書いているのと変わりがない。
別フォームで破棄することが難しいという話の例にはならない。


ひれかつ  2006-08-24 08:54:44  No: 22572

>今回のFormFreeメソッドは、他のフォームのメソッドを使っているだけで、
>普通にFreeと書いているのと変わりがない。
>別フォームで破棄することが難しいという話の例にはならない。
別フォームで普通にFreeして、エラーが発生するから
いいのでは?  Releaseは上手くいく、何が問題?
「Releaseは上手くいく、Freeがエラーになる」十分危険性が分かると思うが?


おいしい  2006-08-24 10:05:17  No: 22573

たまたまエラーが起きない簡単な、しかも本来はしてはいけない使い方の例を出されてもなあ。
おもてないさんのいうように
>普通は class procedure 〜 と「class」を頭につけるけどな。

ついでに
>TTest = class
>  private
>    { Private 宣言 }
>  public
>    { Public 宣言 }
>    procedure Test();
>  end;

procedure Test; virtual;
と定義してあっても
>下に、例ではTTestをCreateしないで使っています。
が問題ないのかと問いたい。


とんこつ  2006-08-24 12:47:19  No: 22574

>まさ 2006/08/23(水) 15:42:50 
>うらないさんの考え方には、3つの間違いがあります。
>ヒントを書くので自分で考えて下さい。

あなたねぇ、いくらなんでも多くの方に失礼過ぎやしませんか?
本当にうらないさんの言ってることが分からないの?
この書き込みをみて私はあなたに対して怒らずにはいられません。
しかも人を茶化したような問題形式…いい加減にしなさい。

あなたが最初に言ってたのは
>まず、気になった点はモーダレスのフォームは、Releaseで必ず解放して下さい。
>FreeAndNilで解放するフォームはモーダルの場合です。
でしょ?
Releaseは私が上に書いた通りの動作をします。
つまりFreeの前にPostMessageしてるだけです。
だから自前でPostMessageすればReleaseと同義になります。

そのことについてFrameさんに
>それでもフォームをFree(FreeAndNil)で破棄するんですか?
>こんなこと常識だと思っていますたが・・・・(-_-;)
などと他人の神経を逆なでするような暴言を吐いて、
あなたは電車内で携帯の使用を注意されて逆切れする高校生ですか?

それで今回、自分でも理解できていなさそうなソースを書いて、問題だぁ?
うらないさんは
「Form2が自分自身をFreeしようとしていると、なんらかわりがない。」
「PostMessageは関係ない」
と教えてくれてるでしょ。
つまり今回出してるソースは、初め問題にしていたReleaseかFreeかとは関係ないし、
Freeの問題を提示しているつもりだけど、Freeの使い方を誤っているのですよ。
本当にそんなことも分からないのですか?

とりあえず次に書き込む事があるならあなたはFrameさんと、うらないさんに謝罪しなさい。少なくとも相手をからかってると解釈されても仕方ない発言に謝罪しなさい。

Freeの件については、簡単に言うとあなたは以下のような例を出してるに過ぎません。
procedure TForm1.Button1Click(Sender: TObject);
 var Button:TButton;
begin
 Button:=TButton.Create(self);
 Button.Free;

 Showmessage(Inttostr(Button.Left));
end;
動くから良いではないでしょ?たまたま動いてるだけです。
つまり、ソース自体に誤りがあるのですよ。


まさ  2006-08-24 19:51:54  No: 22575

Frameさんと、うらないさん不適切な発言すみませんでした。
これからは、技術論でいきましょう。

では、間違った結論になっているので発言します。
はじめに、ことわっておきますが「間違い1」「間違い2」は直接関係ありません。
「間違い1」の結論が
> 一般的なイベントハンドラはSendMessageが起動元になっている場合が多いと思います。
> これはいわゆる割り込みに近いもので他の処理をペンディングしてメッセージの処理をしています。その(割り込み)処理の中でFreeされてしまうとペンディングされている処理が再開された時にオブジェクトがなくなっているのでメモリ保護違反が起きる可能性が高くなります。
に、なっていますが、この意味だと
・ToolButtonは、割り込み後の処理でオブジェクトを参照しているからエラーになっている。
・TButtonは、割り込み後の処理がオブジェクトを参照していないのでエラーにならない。
と言うことですね。ではToolButton・TButton両方を画面に貼り付けて
TButtonよりFormFree()を呼出した時は、どうなりますか?
TButtonの割り込み後の処理は、安全ですよね?  それとも
メッセージ以外の処理が、コンポーネントの組合せで変わりますか?
>「Form2が自分自身をFreeしようとしていると、なんらかわりがない。」
>「PostMessageは関係ない」
>と教えてくれてるでしょ。
>つまり今回出してるソースは、初め問題にしていたReleaseかFreeかとは関係ないし、
>Freeの問題を提示しているつもりだけど、Freeの使い方を誤っているのですよ。
>本当にそんなことも分からないのですか?
私はメッセージとタイミングの問題を提示したつもりです。


んと  2006-08-24 21:52:59  No: 22576

混乱はまささんの最初の頃の発言
>まず、気になった点はモーダレスのフォームは、Releaseで必ず解放して下さい。
>FreeAndNilで解放するフォームはモーダルの場合です。
ここから始まっているような気がするので、それを説明してからだと思うのですが?
まあ、それ以前にスレの質問とは関係なくなってますのでまささんがどうしても必要なら新スレで行っていただいてここはもう〆たほうが良いと思います。
というかこの掲示板で「技術論」ってのはふさわしいのかな?(荒れやすくなるので)


ひれかつ  2006-08-25 05:09:01  No: 22577

「Frame」さん、みえみえ
>Frame 2006/08/20(日) 03:51:59 
>とんこつ 2006/08/24(木) 03:47:19 
同じ人だよね、こんな時間レス出来るということは
仕事してないの?、午前中のレスもないし
まささんのレスにもすぐ返信しているし

>とりあえず次に書き込む事があるならあなたはFrameさんと、うらないさんに謝罪しなさい。
これ、やりすぎ
本当に謝罪させているし…

だいたい、フォーム解放にReleaseを使うのは
当たり前、俺が前いた富士通の現場は、コーディング基準に書いてあった
(わざわざコーディング基準に書くのも富士通らしいが)

「んと」もあんただよね、第三者がいきなりスレを止めるか?
それに本当にスレが止まっているし(みんなあんた?)

まささんの最後の質問にちゃんと答えて
あんたも、まささんに謝罪しなさい。


うーむ  2006-08-25 05:17:01  No: 22578

どうでもいいが、もうこのスレッドはやめにしない?
なにも技術的な価値ないし。非難合戦なら、どこか他でやってください。


はにわ  2006-08-25 09:09:57  No: 22579

荒れ模様もでてくるほど返事が遅くなりすいません。
レス数が多いので驚きましたが・・・

まささんとFrameさんの両方うまくいきました。
フレーム数が多いので今回はFrameさんの方法で進めることにしました。
またBringToFrontもの件もありがとうございました。


???  2006-08-25 09:30:10  No: 22580

> ひれかつ 2006/08/23(水) 23:54:44 
> >今回のFormFreeメソッドは、他のフォームのメソッドを使っているだけで、
> >普通にFreeと書いているのと変わりがない。
> >別フォームで破棄することが難しいという話の例にはならない。
> 別フォームで普通にFreeして、エラーが発生するから
> いいのでは?  Releaseは上手くいく、何が問題?
> 「Releaseは上手くいく、Freeがエラーになる」十分危険性が分かると思うが?

「Releaseは上手くいく、Freeがエラーになる」という方向性ならいいのですが、
「別フォームでFreeすることがいかに難しいか」ということに対する回答には、なりえません。
・・ということでしょ?
TAplicationのDispatchMessageで処理した一つのメッセージが流れている途中にすぎないから、
TForm2.ToolButton1Click だろうが、TForm1.Form2Free; だろうが、やってることは同じだから、結果はかわらない。

ToolButtonがエラーになり、Buttonがエラーにならないのは内部的な作りの問題。
こういうことがあるから、(今回の例で言えば)Form2上のコントロールから、自身を破棄するには、Releaseを使いなさい。
でも、Form1側にForm2の破棄処理を書いたからと言って、Form2上のコントロールから発生するイベント内で
Form1側のForm2の破棄処理を実行しても、所詮Form2が自殺しているのと同じ。

今、Delphiの環境がないけど、ToolButtonClickの自殺Freeを、Releaseに変更したら、エラーはでなくなるでしょう。
でも、Application.ProccessMessages; をさらにつっこんだら、エラーでない?

それが、この辺で言ってる事なのかもしれないが、よくわからなかった。
> まさ 2006/08/22(火) 16:56:06 
> (略)
> 私の考えではFreeを使って良い場合は、PostMessageメッセージが使われていないか
> またはFreeが実行される前に全てのPostMessage処理が実行を終了していることを
> 保証しないといけません。

>(実話は私も直接Releaseを使いません(Freeも使いません)
じゃ、どうやってるの?
これを聞きたい。
Releaseの最終結果はFreeだし、Freeなくしてメモリの解放はありえないんじゃない?
そういうことじゃなく、OnCloseでcaFree?

ま、FreeでもReleaseでも、参照している変数がnilにならずに放置されていれば、
安全に破棄できても、意味ないけどねぇ。


とんこつ  2006-08-25 11:46:43  No: 22581

既に???さんが書かれているようですが
私も大口叩いた以上、とことんつき合わせて頂きます。

>まさ 2006/08/22(火) 17:24:55 
で書かれている、問題1は
オブジェクトをFreeしてしまった後に、そのオブジェクトにアクセスしています。
ToolButtonでアクセス違反が起きて、Buttonでは起きないのは単に偶然です。
そもそも、Freeしてしまったオブジェクトにアクセスしてはいけません。
これは、そのオブジェクトが格納されていたメモリのアドレスのロックが解除されたため、以前オブジェクトがあったメモリ位置が他のプロセスによって書き換え可能な状態になっているからです。

オブジェクトインスペクタで貼り付けられたコントロールの生成、開放については私も勉強不足で、細かい点は分かりませんが、ToolButtonでアクセス違反が発生するのはTToolbarのDestroyでしっかり開放されているからだと思います。

私が昨日書いたように別にFreeしてもポインタもそのメモリのデータもそのままであれば、あたかも正常にアクセスできているかのように見えることがありますが、これはデータとして保障されたものではありません。

この例でアクセス違反を起こすのであれば、
procedure TForm2.FormDestroy(Sender: TObject);
begin
  Form2.Canvas.TextOut(0,0,'test');
end;
とかしてみれば例外は発生できます。
無論、Formを単体で作って同じことをしても例外は出ません。
まささんの例ではFormがDestroyされる以前にFormのポインタにnilが代入されているためです。

>ひれかつ 2006/08/24(木) 20:09:01 
あのねぇ…
私は「Frame」さんで「もん」とさんでもありません。
てか、人に謝罪しろとまで言った以上、私はまささんにとことん付き合うつもですし、
コロコロIDを変えるようなことはしません。何なら管理人に頼んでIPアドレス見せてもらったらどうですか?
私が他の2名でないことを証明する分には管理人さんにその旨をお話して開示させてもらって結構です。
朝9時から夜12時まで働くのがそんなにあなたの環境では珍しいことですか?
それに私は知らない人に対して主に敬語です。
あなたも私に対して謝罪を要求するのであれば、それなりの態度と技量で接してください。

私は異常なスレの伸びをみて途中参加した者ですし、未だに始めの方をちゃんと読んでいません。
確かにちゃんと付き合うのなら全部読む必要があるのは分かってます。
>まさ 2006/08/22(火) 17:24:55 
が何を言おうとしたソースなのかすら未だ把握していないのも事実です。
見ると「うらないさん」の回答がそのままなのにそれに対する返信に誠意の無さを感じたのにこれはいかんと感じたまでです。
なんとか明日までには目を通しておきます。


まさ  2006-08-25 21:39:44  No: 22582

すみなせん。私の発言が間違っていますた。
>まず、気になった点はモーダレスのフォームは、Releaseで必ず解放して下さい。
>FreeAndNilで解放するフォームはモーダルの場合です。
すみませんでした。モーダレスのフォームもFreeで解放して下さい。
私が過ちを認めたので、このスレを終わりにして下さい、お願いします。


???  2006-08-27 07:50:11  No: 22583

> すみませんでした。モーダレスのフォームもFreeで解放して下さい。
ToolButtonの例でFreeが危険だと言う例を挙げているのに、なぜこの発言ですか?

私は、「別フォームでFreeすることがいかに難しいか」という例になっていないと述べたに過ぎません。

正直、そんなことより、
>(実話は私も直接Releaseを使いません(Freeも使いません)
これが気になる発言です。
FreeやReleaseが一般的な開放方法であれば、いったいどういう手法をとって<安全>に
開放しているのか?

ま、別にヒントだけでもいいんですけどね。
技術の足しになりうるものであれば、吸収させて頂きたいです。


TS  2006-08-27 19:15:37  No: 22584

>私が過ちを認めたので、このスレを終わりにして下さい、お願いします。
沢山の意見が出ました、始めから読めば結論は既に出ると思います。
これ以上の議論は必要無いように思います。
私からもこれスレが終わりますようお願いします。


  2006-08-27 20:15:34  No: 22585

〆切ります。以下同文(⌒◇⌒;)A


結論でてますか?  2006-08-28 01:00:37  No: 22586

まささんは勘違いしていますね。
このサンプルプログラムは、私の環境(Delphi7)では
エラーになりません、まささんは別環境での動作を意識してないですね。
この辺りが、まささんと他の人との話がかみ合っていない原因だと思いますよ。

今日たまたまDelphi6で実行したところ、うまくエラーになりました。
このプログラムはかなり環境に依存するみたいで、Delphi6でもたまにエラーになりません。

Delphi6の環境でエラーになる原因は、まささんが言っている通り
ウィンドウズからのPostMessage(WM_LBUTTONUPが主に多いです)が起点になっていますね。
エラーになったりならなかったりするのは、多分PostMessageとFreeAndNilのタイミングだと思います。
(まささん、全ての環境でこのPostMessageがエラーになるサンプルプログラムを作るのは難しいと思いますね)

私の環境では他の人が言っているToolButton1Clickの後処理でエラーなっているとは思えませんでした。
試しに、メッセージとしてでは無くメソッドとして直接起動してみましたが
エラーになることはありませんでした。
(ソースです、Form2でメッセージを発生しないようにForm1から起動しています)
procedure TForm1.Button2Click(Sender: TObject);
begin
  Form2.ToolButton1.Click;
end;
これでエラーにならない以上、エラーの起点はPostMessageだと思いますが
環境に影響されるプログラムなので、断定は出来ませんが

とんこつさん、???さんは後処理のどの場所でエラーになりますか?  またどうやって確認したんですか教えて下さい。

このサンプルプログラムでは全ての人に、正しく危険性を伝える事は出来ないと思いますが
動くようになった私は、まささんが言っている事が正しいと思います。


結論でてますか?  2006-08-28 01:05:23  No: 22587

まささん、私も
>(実話は私も直接Releaseを使いません(Freeも使いません)
が気になります。私はまささんは技術力のある技術者だと思います
ぜひ教えて下さい。


えーと  2006-08-28 04:24:28  No: 22588

> 動くようになった私は、まささんが言っている事が正しいと思います。

あのですね、あるときはうまくいき、あるときはうまくいかないプログラムは
よいプログラムではありません。TForm で自分のイベントハンドラから Free
すると、必ずエラーになるとはかぎりません。エラーになるときがあるのです。
ですから、Free ではなく Release を使うべきなんです。

PostMessage() と SendMessage() は、Windows のようなイベント駆動型の
プログラムを理解するのにはその区別は必須です。イベントハンドラのような
関数や手続きを呼び出すと、処理が終わったら呼び出された連鎖の順番に遡って
結局メッセージループにたどり着きます。Free を使った場合エラーになるのは
この呼び出しの連鎖を遡る事が出来なくなるからです。でも、それができる場合も
あって、Free でメモリがクリアされるタイミングが微妙です。Release を使うと
この危険性がなくなります。なぜなら、メッセージループに戻ってから、Free が
実行されることが保証されるからです。

逆に言うと、Free されたインスタンスを遡る必要がないハンドラでは、Free や
FreeAndNil を使っても一向に差し支えありません。


???  2006-08-29 09:45:50  No: 22589

> このサンプルプログラムは、私の環境(Delphi7)では
> エラーになりません、まささんは別環境での動作を意識してないですね。

「内部的な作りの問題」と、私が答えているでしょ?
バージョンが違えば、VCLの中身も違う可能性がある。
同じバージョンでコンパイルし、OSが違う環境で、確実に出る・出ないが
再現できるなら、それこそ環境の問題です。
勘違いしないように。

ちなみにどんなエラーが出ましたか?
当方はDelphi5 ですが、「親コンポーネントが〜」だったかで、
Parent=nil のため、ウインドウハンドルが取得できないエラーです。
TWinContolのどこかで、DefWindowProc(Handle, あたり。
その点、誰かの言っているアクセス違反ではありませんがね。

> procedure TForm1.Button2Click(Sender: TObject);
> begin
>  Form2.ToolButton1.Click;
> end;
話の問題点わかってないでしょ。

Form2のコンポーネントのイベントから始まる自殺処理のことで
ぐだぐだ言ってるのに、これはForm1がForm2を殺す他殺なの。

> 動くようになった私は、まささんが言っている事が正しいと思います。
ということは、どんなときも「Freeを使ってもいい」という結論ですね。
だったら、あなたのプログラムで、フォームの破棄は全て、自殺Freeで
書いてください。

> 今日たまたまDelphi6で実行したところ、うまくエラーになりました。

えーと さんの言うとおり。
> あるときはうまくいき、あるときはうまくいかないプログラムは
> よいプログラムではありません。

『OSが違うから、終了時にエラーが出ることがあります。』
あなたは、こういう状況を放置するわけですね。

「結論でてますか?」さんより、まささんのほうが、よっぽど技術も知識ありますよ。


結論でてますか?  2006-08-30 05:49:18  No: 22590

>えーと 2006/08/27(日) 19:24:28 
>あのですね、あるときはうまくいき、あるときはうまくいかないプログラムは
>よいプログラムではありません。TForm で自分のイベントハンドラから Free
>すると、必ずエラーになるとはかぎりません。エラーになるときがあるのです。
>ですから、Free ではなく Release を使うべきなんです。
あのですね、私が何時Freeを使うと書きました
一行も書いてないですよね
私は、まささんの意見が正しいと言っただけです
最初から読んで書いた方がいいですよ

まささんの意見
まさ 2006/08/19(土) 00:43:22 
>まず、気になった点はモーダレスのフォームは、Releaseで必ず解放して下さい。
>FreeAndNilで解放するフォームはモーダルの場合です。

Frameさんの意見
Frame 2006/08/19(土) 17:11:55 
>そのフォームまたはその子フォームのイベントハンドラ以外からではFreeAndNilやFreeをすることは構いません。
これが今回の議論の始まりです
私はFrameさんの意見が正しいとは書いていませんよね
私も、えーとさんと同じく「Free ではなく Release を使うべき」と思っていますから


えーと  2006-08-30 08:48:18  No: 22591

Free か Release かの議論と、モーダルかモードレスかは全く関係ありません。
ですから、最初からまささんは間違っています。その点については議論の余地はありません。


えーとにえーと  2006-08-30 09:39:42  No: 22592

>Free か Release かの議論と、モーダルかモードレスかは全く関係ありません。
>ですから、最初からまささんは間違っています。その点については議論の余地はありません。
えーとさんは、なにが言いたいの?
「結論でてますか?」さんが言っているのは、反論する前に「ちゃんと読め」と言うことですよ、人の意見を読まないで自分の意見だけ書いてどうする


Syake  2006-08-30 10:00:40  No: 22593

「えーとにえーと」さんに一票


えーと  2006-08-30 12:08:14  No: 22594

どうも誤解があるようですが、

>そのフォームまたはその子フォームのイベントハンドラ以外からではFreeAndNilやFreeをすることは構いません。

わたしはこっちが正しいと思っています。


えーと  2006-08-30 12:13:55  No: 22595

ついでに言えば

>まず、気になった点はモーダレスのフォームは、Releaseで必ず解放して下さい。
>FreeAndNilで解放するフォームはモーダルの場合です。

これは誤りだと思っています。

ここまでで、捨てハンかもしれませんは「えーと」での投稿は一貫しています。


とんこつ  2006-08-30 12:14:47  No: 22596

眠い…一応質問には応えておきます
>結論でてますか? 2006/08/27(日) 16:00:37 
>とんこつさん、???さんは後処理のどの場所でエラーになりますか?  
>またどうやって確認したんですか教えて下さい。

>まさ 2006/08/22(火) 17:24:55 
このソースですよね?
Delphi7pro,WindowsXP
コンパイル→
Form1のButton1Click→Form2のToolButton1Click→
Form1のButton1Click→Form2のToolButton1Click→例外発生

>エラーになったりならなかったりするのは、多分PostMessageとFreeAndNilのタイミングだと思います。
これは正しいですが、今回のエラーはWM_LBUTTONUPが原因ではありません。
>動くようになった私は、まささんが言っている事が正しいと思います。
動くだけでは問題があるということを私は以下のレスで言っていますし、このソースの問題点も書いてあります。
>とんこつ 2006/08/24(木) 03:47:19 
>とんこつ 2006/08/25(金) 02:46:43 
もし「結論でてますか?」が私に質問するのであればご一読してください。

あと意見は技術的に書きましょう。話題の中心がプログラミング言語なんですから。
>結論でてますか? 2006/08/29(火) 20:49:18 
>あのですね、私が何時Freeを使うと書きました
>一行も書いてないですよね
>私は、まささんの意見が正しいと言っただけです
「まささんの意見が正しい」がいつ時点のまささんに掛かってるかが問題ですが、
「まさ 2006/08/22(火) 17:24:55」 のソースに対して正しいといってるのであれば誤解を受けても仕方ないと思います。このソースではFreeの誤った使い方をしているためです。


えーと  2006-08-30 12:49:07  No: 22597

> 「まささんの意見が正しい」がいつ時点のまささんに掛かってるかが問題ですが、

すみませんが、まささんの投稿で、個別に正しいところはあるんでしょうか?


???  2006-08-31 10:31:31  No: 22598

えーと 2006/08/30(水) 03:49:07 
>すみませんが、まささんの投稿で、個別に正しいところはあるんでしょうか?

ここかな?
> まさ 2006/08/19(土) 00:43:22 
> あと、インスタンスを一つにしたい場合は、Singletonパターンを使った方が良いで

さて本題
とんこつ 2006/08/30(水) 03:14:47
> 「まささんの意見が正しい」がいつ時点のまささんに掛かってるかが問題ですが、

ずばりこれでしょ?
-------------------------------
まさ 2006/08/19(土) 00:43:22 
>まず、気になった点はモーダレスのフォームは、Releaseで必ず解放して下さい。
>FreeAndNilで解放するフォームはモーダルの場合です。
-------------------------------

でも俺は、こっち。
Frame 2006/08/19(土) 17:11:55 
>そのフォームまたはその子フォームのイベントハンドラ以外からではFreeAndNilや
Freeをすることは構いません。

「モーダレスのフォームは、Releaseで必ず解放」
ここの「必ず」とは思ってないからね。

「Free ではなく Release を使うべき」と考えている以上、
Frameさんの意見が正しいと仮定しても、Frameさんの意見は
受け容れられないんでしょ?

でも、まささんのサンプルが動いたら「Releaseじゃなくてもいいよね?」ってなるよね?
結局何が言いたい?


???  2006-08-31 10:42:09  No: 22599

> とんこつさん、???さんは後処理のどの場所でエラーになりますか?

もう一回プロジェクト作り直してやってみたよ。
エラーがでたのは、ControlStyleを参照してアクセス違反

procedure TControl.DoMouseUp(var Message: TWMMouse; Button: TMouseButton);
begin
ここ>>  if not (csNoStdEvents in ControlStyle) then
    with Message do MouseUp(Button, KeysToShiftState(Keys), XPos, YPos);
end;

先のレスでエラーが出たのはココ

procedure TWinControl.WndProc(var Message: TMessage);
//(略)
    WM_MOUSEFIRST..WM_MOUSELAST:
      if IsControlMouseMsg(TWMMouse(Message)) then
      begin
        if Message.Result = 0 then
//ココ          DefWindowProc(Handle, Message.Msg, Message.wParam, Message.lParam);
        Exit;
      end;

ちゃんとあなたの質問に回答してるんだから、なんか反応してよね。


ん?  2006-08-31 19:46:20  No: 22600

遅参入です。

争点が

『モーダレスのフォームは、Releaseで必ず解放
FreeAndNilで解放するフォームはモーダルの場合
(by まさ 2006/08/19(土) 00:43:22)』

『そのフォームまたはその子フォームのイベントハンドラ以外からで、Freeをすることはかまわない
(By Frame 2006/08/19(土) 17:11:55)』

であれば、『そのフォームまたはその子フォームのイベントハンドラ以外から、
Freeして<<エラーを出す>>』サンプルが提示できなければ、Frameさんの意見を
覆すことはできないのでは?

『モーダレスのフォームは、Releaseで <<必ず>> 解放』  が正しいのであれば、
『そのフォームまたはその子フォームのイベントハンドラ以外から、
Freeして<<エラーを出す>>』ことが可能のはずです。

そうでなければ、まささんの意見が正しいとは言い切ることはできません。
結論でてますか?さんの意見として、「FreeよりReleaseを使うと考えている」
と答えておられますが、「考えている」以上にはなりえないです。
考えは考えであって、正しいかどうかを証明しているわけではないでしょう?
『そのフォームまたはその子フォームのイベントハンドラ以外から、
Freeして<<エラーが出る(ことがある)>>』から『Releaseである必要がある』
ということを。


えーとにえーと  2006-09-01 04:47:45  No: 22601

>ここまでで、捨てハンかもしれませんは「えーと」での投稿は一貫しています。
えーとさん他にどの名前で投稿したの?


えーと  2006-09-01 09:14:24  No: 22602

このすれでは「えーと」以外にありません。他のスレッドでは別のハンドルで
投稿したことがあります。


えーと  2006-09-01 09:26:53  No: 22603

> 「結論でてますか?」さんが言っているのは、反論する前に「ちゃんと読め」
> と言うことですよ、人の意見を読まないで自分の意見だけ書いてどうする

読んでますよ。

> 結論でてますか? 2006/08/27(日) 16:00:37 

に対するわたしのレス

> えーと 2006/08/27(日) 19:24:28 

どこかおかしいですか? あと

> 結論でてますか? 2006/08/29(火) 20:49:18 

に対するわたしのレス

> えーと 2006/08/29(火) 23:48:18 

どこがおかしいのでしょう?

結論でてますか?さんの

> このサンプルプログラムでは全ての人に、正しく危険性を伝える事は出来ないと思いますが
> 動くようになった私は、まささんが言っている事が正しいと思います。

に対するレスです。自殺イベントハンドラでは、必ずエラーになるわけではないが、
エラーになることがあるので、ハンドラを出てから Free することが保証されている
Relesae を使うべきである。自殺ハンドラ以外なら free でも FreeAndNil でも
よろしい、ということです。

これが正しくないことを証明するには、上の ん? さんの最後に書かれている部分を
例示する必要があります。


争点  2006-09-01 12:01:02  No: 22604

ん?さん、争点が違うと思いますよ。

>Frame 2006/08/20(日) 16:07:44 
>一般的なイベントハンドラはSendMessageが起動元になっている場合が多いと思います。
>これはいわゆる割り込みに近いもので他の処理をペンディングしてメッセージの処理をしています。その(割り込み)処理の中でFreeされてしまうとペンディングされている処理が再開された時にオブジェクトがなくなっているのでメモリ保護違反が起きる可能性が高くなります。
>またPostMessageによるアイドルループでのメッセージイベントハンドラでは安全にFreeをすることが可能です。(ちゃんと設計されてれば)
>(モードレス/モーダルとは直接関係ありません)

>まさ 2006/08/19(土) 23:33:07 
>私の書き方が悪かったのかもしれませんが、私の考えは
>>>・画面が実行中(内部コードがフォームのオブジェクトを参照する可能性があるもの):Release
>>>・画面が閉じたもの(内部コードがフォームのオブジェクトを参照しないもの):Free(FreeAndNil)
>>>(すみません、この辺りの考え方を単純にモーダル・モードレスと書いてしまいました、厳密には違いますが...^^;)
>だと思います。たしかに厳密には「タイミングの問題」だと思いますが、別フォームから見た場合
>  ・モーダルは、確実に終了が分かる。
>  ・モードレスは、内部コードがオブジェクトを参照している可能性が常にある。
>よって、モーダル/モードレスでFreeAndNilとReleaseを使い分けています。

この二つの発言が、お互いの考えだと思います。


えーと  2006-09-01 19:55:10  No: 22605

争点というか、

> 別フォームから見た場合
>  ・モーダルは、確実に終了が分かる。
>  ・モードレスは、内部コードがオブジェクトを参照している可能性が常にある。
>よって、モーダル/モードレスでFreeAndNilとReleaseを使い分けています。

これは、

わたしはフォームの色が Color := btnFace のときは Free を、それ以外の
ときは Release を使うようにしています。

と同じくらい、関係ないことを結び付けてるように思いますが。そもそも争点に
なってないと思います。


えーと  2006-09-01 19:56:35  No: 22606

× Color := btnFace
○ Color := clBtnFace


争点  2006-09-02 19:15:43  No: 22607

えーと 2006/09/01(金) 10:55:10 
>わたしはフォームの色が Color := btnFace のときは Free を、それ以外の
>ときは Release を使うようにしています。
>と同じくらい、関係ないことを結び付けてるように思いますが。そもそも争点に
>なってないと思います。
えーとさん本当に、こう思っているんですか?
まささんが言っているのは、メッセージループ中にはFree(FreeAndNil)を使わないと言うことです
その基準にモーダル・モードレスを使っていると言うことです。
フォームの色はメッセージループに関係ありませんが、モーダル・モードレスはメッセージループに
関係してきますよ。

えーと 2006/09/01(金) 00:26:53
>これが正しくないことを証明するには、上の ん? さんの最後に書かれている部分を
>例示する必要があります。
えーとさんは、ん? さんの争点で行いたいようですが
まささんが
>(すみません、この辺りの考え方を単純にモーダル・モードレスと書いてしまいました、厳密には違いますが...^^;)
と間違いを認めている以上、争点にはなりえません。


えーと  2006-09-02 19:55:13  No: 22608

> まささんが言っているのは、メッセージループ中にはFree(FreeAndNil)を使わないと言うことです

メッセージループじゃなくて、モーダルループですよね。TForm.ShowModal の中の
メッセージ処理のループです。モーダル表示されているフォームは、普通、それが
Close されない限り、ShowModal から復帰しません。ですから、これから呼び出
されるハンドラは、すべて自殺ハンドラです。Free や FreeAndNil を使わないのは
当然です。

争点になってないと思います。


えーと  2006-09-02 20:23:50  No: 22609

なるほど。上のように書くと、確かに誤解されますね。

> 別フォームから見た場合
>  ・モーダルは、確実に終了が分かる。
>  ・モードレスは、内部コードがオブジェクトを参照している可能性が常にある。
>よって、モーダル/モードレスでFreeAndNilとReleaseを使い分けています。

これが問題だと思うのは、

> モーダル/モードレスでFreeAndNilとReleaseを使い分けています。

の部分だと思います。これは、一般解である

>そのフォームまたはその子フォームのイベントハンドラ以外からではFreeAndNilやFreeをすることは構いません。

の一例ですよね。ShowModal は、イベントハンドラではなく TForm の
メソッドですが。ですから、普通の状況では

>まず、気になった点はモーダレスのフォームは、Releaseで必ず解放して下さい。
>FreeAndNilで解放するフォームはモーダルの場合です。

これは誤りだと思っています。正反対になってますね。

わたしなら

・モーダルフォームはReleaseで必ず解放して下さい。
・モードレスフォームは、自分自身のハンドラに由来する処理では Release を、
それ以外なら Release Free FreeAndNil いずれでもOKです。

と書きます。


えーと  2006-09-02 20:36:11  No: 22610

すみません。間違えました。

・モーダルフォームはReleaseで必ず解放して下さい。

これは誤りです。モーダルループ中では、Free でも Release でも自殺できませんね。

単純に ModalResult を設定するか、Close で閉じて、ShowModal から復帰したら
Free でも Release でも OK ですが。


えーと  2006-09-02 20:48:52  No: 22611

そうか、これでは

>えーと 2006/09/01(金) 10:55:10 

この投稿は間違っていますね。

申し訳ありませんでした。


えーとにえーと  2006-09-02 23:52:57  No: 22612

えーとさん、「ん?」さんの争点と言っている
>『そのフォームまたはその子フォームのイベントハンドラ以外からで、Freeをすることはかまわない
>(By Frame 2006/08/19(土) 17:11:55)』
この発言の前文に書かれている
Frame 2006/08/19(土) 17:11:55 
>>まず、気になった点はモーダレスのフォームは、Releaseで必ず解放して下さい。
>>FreeAndNilで解放するフォームはモーダルの場合です。
>モーダルだからとかモードレスだからという違いではないですね。
>フォームのインスタンス中から自分を直接Freeすることは出来ません。
>そのような用途のためにReleaseがあります。
と書いていある(意識的か無意識か分からんが、この発言が削除されている)
えーとさん、これは正しいの?


zebra  2006-09-03 00:45:11  No: 22613

Frameさんの意見に同意ですが、まささんの言っている事も少しだけ分かる気がします。

自分も良く分かっていない部分が多々ありますが、Releaseを使うのは自殺するときのみでそれ以外はFreeでいいと思います。
別フォームからみたら、モーダルでもモードレスでもFreeで構わないと。

Releaseを使うのはモードレスで自殺するとき、モーダルは常に外部からしか開放できないのでFreeを使う、故にモードレスはReleaseで、モーダルはFreeという考えになるのは理解できます。

ですが、モードレスは<必ず>Releaseというのは間違いだと思います。
何故かと言うと、例えばForm1からForm2をFreeする場合、必ず安全に解放されることが保証されているからだと思います。これは、Form1もForm2も同じメインスレッドで動いているからじゃないでしょうか?
別スレッドであれば、また問題ありそうですけど。

それと、
>まさ 2006/08/19(土) 18:53:23 
>Free直後に内部コードがフォームオブジェクトを
>参照してアクセス違反が起きる可能性があるます。
とありますが、Freeされていれば内部コードが・・・っていうのはおかしいような気がします。内部コードがFreeされたフォームの内部コードの場合ですが・・


えーと  2006-09-03 06:43:40  No: 22614

> えーとにえーと 2006/09/02(土) 14:52:57 

> >モーダルだからとかモードレスだからという違いではないですね。
>>フォームのインスタンス中から自分を直接Freeすることは出来ません。
>>そのような用途のためにReleaseがあります。
>と書いていある(意識的か無意識か分からんが、この発言が削除されている)
>えーとさん、これは正しいの?

正しいです。

ですが、モーダル表示されている場合は、Release でもだめですね。
ですから、一つだけが例外です。

モーダルフォームでは、自殺でも Release は使えない。

ということです。

それ以外は、特にモーダルかモードレスかに関係なく

>>そのフォームまたはその子フォームのイベントハンドラ以外からではFreeAndNilやFreeをすることは構いません。

は成り立ちます。

興味深いのは、メインのメッセージループは、Application.Run の中にあって
どのフォームにも属してないので、上の一般論が成り立ちます。しかし、モーダル
ループは、表示中のモーダルフォームのメソッドなので PostMessage に相当する
Release でも、その結果呼び出される Free からの復帰は、モーダルループに
返ってくるので、エラーになることです。

ま、一般にはモーダルなフォームは自殺する必要はないですし、開放するならShowModal を呼び出したあとに開放するといいので、この点を問題視する
必要はないと思いますが。

今回、このスレッドが混乱して長くなったのは、この特殊な例外にこだわった人と
わたしのように一般論を支持する人の議論がすれ違っていたんだと思います。


えーと  2006-09-03 08:51:41  No: 22615

> 今回、このスレッドが混乱して長くなったのは、この特殊な例外にこだわった人と
>わたしのように一般論を支持する人の議論がすれ違っていたんだと思います。

ずっと考えていたんですけど、そもそもの発端である

>まさ 2006/08/19(土) 00:43:22 

>まず、気になった点はモーダレスのフォームは、Releaseで必ず解放して下さい。
>FreeAndNilで解放するフォームはモーダルの場合です。

これですけど、最初の一行

>まず、気になった点はモーダレスのフォームは、Releaseで必ず解放して下さい。

これは、間違いです。というか、どんな場合も Release を使えば安心、ということ
はあるでしょうけど、インスタンス変数を nil にセットしたいときもありますので
自殺でない場合は、Free や FreeAndNil を使ってもいいと思います。

問題なのは、次の

> FreeAndNilで解放するフォームはモーダルの場合です。

これなんですね。これは、上に上げた「特殊な例外」とは関係なく、たんに
ShowModal のあとなら、FreeAndNil でも OK ということですよね。
これは、当たり前であって、ShowModal を実行するハンドラは自殺ハンドラでは
無いからです。

ですから、たんに自殺ハンドラでないことがほぼ保証される一例にすぎないことを
一般論として主張されたのが議論が長引いた原因だと思います。


zebra  2006-09-03 14:27:23  No: 22616

>えーと 2006/09/02(土) 21:43:40 
>モーダルフォームでは、自殺でも Release は使えない。

素朴な疑問なのですが、別にモーダルでReleaseが使えないって事ではないんじゃないでしょうか?
モーダルは必ずCloseしなければならない。
Releaseは非同期Free。
なので

procedure TForm2.Button1Click(Sender: TObject);
begin
  Self.Release;
  Self.Close;
end;

こうすれば、Form2が閉じられた後に解放されることが保証されるはず。
勿論こんな事する意味がないですけど。
だからモードレスはRelease、モーダルはFreeとかいう制限は特に無いと思うのですが。

それと、まささんの言われている事は、特殊な例外というほどの事では
無いように思いました。
ちょっとした(だけど大きな)勘違いと、誤解を招きやすいヘルプの所為かなと。

最後に、
>えーと 2006/09/02(土) 23:51:41 
>これは、間違いです。というか、どんな場合も Release を使えば安心、ということ
>はあるでしょうけど、インスタンス変数を nil にセットしたいときもありますので
>自殺でない場合は、Free や FreeAndNil を使ってもいいと思います。

例えばForm1からForm2(モードレス)を解放するときに
procedure TForm1.Button1Click(Sender: TObject);
begin
  Form2.Free;
  Form2 := nil;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  FreeAndNil(Form2);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Form2.Release;
  Form2 := nil;
end;
この3つのメソッドは同じ事をしているので
>インスタンス変数を nil にセットしたいときもありますので
この様な理由でFree或いはFreeAndNilを使うわけではないと思います。

細かいツッコミばかりですみません。揚げ足取りが目的ではありません。
えーとさんのように見識ある方が発言される事は多くの方が信用される
と思うので敢えて突っ込んでみました。

個人的な結論としては、
外部から同期解放ならFree、内部或いは外部から非同期解放ならReleaseということになると思います。


えーと  2006-09-03 14:47:08  No: 22617

> procedure TForm1.Button1Click(Sender: TObject);
> begin
>   Form2.Release;
>   Form2 := nil;
> end;
> この3つのメソッドは同じ事をしているので

これだけ同じではありませんよ。

Release は遅延の Free ですから、実際に Free されるより変数 Form2 が nil 
になる方が先になりますのでマズイです。

また、Free してから nil を代入することと FreeAndNil とは同等ではありません。
これは FreeAndNil のソースを見てみると分かります。


えーと  2006-09-03 14:52:02  No: 22618

> それと、まささんの言われている事は、特殊な例外というほどの事では
> 無いように思いました。

上にも書きましたように、「特殊な例外」は「えーとにえーと」さんの指摘よるものです。

まささんのは、

> FreeAndNilで解放するフォームはモーダルの場合です。

これは、繰り返しになりますが、ShowModal 直後の、自殺ハンドラでないことが
保証されている場合は Free をつかってもかまわない、ってことの一例にすぎ
ません。


zebra  2006-09-03 17:51:37  No: 22619

まず、前提としてメインスレッドしか存在しないという事で話しをしています。
もしかして、皆さんは複数のスレッドが存在するという前提で話しをされて
いたんでしょうか?

>> procedure TForm1.Button1Click(Sender: TObject);
>> begin
>>   Form2.Release;
>>   Form2 := nil;
>> end;
>> この3つのメソッドは同じ事をしているので

>これだけ同じではありませんよ。

>Release は遅延の Free ですから、実際に Free されるより変数 Form2 が nil 
>になる方が先になりますのでマズイです。

確かに厳密には全く同じではないですが、Form2にnilが先に代入されて
TForm1.Button1Clickを抜けた直後にアイドルループでFreeされる訳ですよね?
どのようにマズイのか分かりません。
あまり経験が無いので分からないだけかもしれませんが、教えて頂けると
ありがたいです。

>また、Free してから nil を代入することと FreeAndNil とは同等ではありません。
>これは FreeAndNil のソースを見てみると分かります。

たしかに、これも厳密には全く同じではありませんね。
しかし、FreeAndNilは別スレッドから参照される可能性があるので、先に
参照変数にnilを代入して安全を確保してから解放しているというだけの
事のように思いますが、メインスレッドしか存在しない状況ではどちらも
同じと考えて差し支えないように思います。


えーと  2006-09-03 22:28:37  No: 22620

> まず、前提としてメインスレッドしか存在しないという事で話しをしています。

たしかに、その前提なら、どれもにたようなものですね。FreeAndNil もいらないですし。


争点  2006-09-04 08:55:13  No: 22621

議論も進んだのでここで、もう一回争点を再確認した方が良いと思いますので、
私がまとめてみました。間違っていると思ったら指摘して下さい。

・モーダルフォーム
    これは、「FreeAndNilで解放」で意見が一致出来たと思います。

・モーダレスフォーム:
    まささんの意見 :Releaseで解放する
    Frameさんの意見:そのフォームまたはその子フォームのイベントハンドラ以外からで、Freeをすることはかまわない
この意見ですが、まささんの意見が間違いとは言えないので
どちらの意見がより好ましいか、と言う事になると思います。
これで、議論を進めてはどうでしょうか?


zebra  2006-09-04 18:23:00  No: 22622

自己レス
>外部から同期解放ならFree、内部或いは外部から非同期解放ならReleaseということになると思います。

すみません、勘違いしていました。
外部から非同期解放とか無理ですね。。


オブ脳  2006-09-05 07:29:08  No: 22623

私は、まささんの意見に賛成ですね
Frameさんの考えは技術的に出来ると言うだけで、それが正しいとは限りません。

オブジェクト指向ではクラス間の依存関係を、なるべく弱くしないといけません。
依存関係が強いとメンテや拡張が大変になります。
例えば、今Freeを使っても大丈夫だとしても
プログラムを拡張(継承)してFreeが使えなくなった場合
二つのクラスを修正しないといけなくなりますね。

この辺り、まささんの方がしっかり考えていると思います
インスタンス作成時にも
他の人たちがハードコーディングで作成しているのに対して
>a:=tframe2.Create(self);

まささんはデザインパターンでインスタンス作成を抽象化して
依存関係を少なくしていますね。
>class function TFrame2.GetInstance(AOwner: TComponent;ATop,ALeft: Integer): TFrame2;
>begin
>  if not Assigned(Singleton) then
>  begin
>    Singleton      := TFrame2.Create(AOwner);
>  end;
>  Singleton.Top    := ATop;
>  Singleton.Left   := ALeft;
>  Singleton.parent := TForm(AOwner);
>  Singleton.Show;
>  Singleton.BringToFront;
>  Result := Singleton;
>end;
まささんの方が正しいオブジェクト指向だと思いますよ。


とんこつ  2006-09-05 10:02:19  No: 22624

問題点がごっちゃになってますし、
>争点 2006/09/03(日) 23:55:13 
でのまとめも不正確なので、まとめなおします。

とりあえず、まささんは3点の技術を提供してくださいました。
  インスタンスを一つにしたい場合のSingletonパターンの作成方法
  モーダレスのフォームは、Releaseで必ず解放
  モーダルフォームの場合は、FreeAndNil

これに対してFrameさん
>Frame 2006/08/19(土) 17:11:55 
>モーダルだからとかモードレスだからという違いではないですね。
>フォームのインスタンス中から自分を直接Freeすることは出来ません。
>そのフォームまたはその子フォームのイベントハンドラ以外からでは
  FreeAndNilやFreeをすることは構いません。

  フォームの開放は、モーダル、モードレスは関係ない。
  フォームのインスタンス中から自分を直接Freeすることはできない
  そのフォームまたはその子フォームのイベントハンドラ以外からでは
    FreeAndNilやFreeをすることはOK

です。
私には、モーダレスとモーダルフォームで何故場合分けができるのかが理解できません。
また、フォームのインスタンス中から自分を直接Freeすることはできないというのも当然にしか思えないので、直接Freeして良い条件が分かりません。そのフォームまたはその子フォームのイベントハンドラ以外からのFreeはインスタンス中のReleaseと同義であるためわざわざ外からReleaseする必要が無いのも当然にしか思えません。(Releaseしても構わないがする意味が無い)

つまり、まささんの
  モーダレスのフォームは、Releaseで必ず解放
  モーダルフォームの場合は、FreeAndNil
がインスタンス内外であるかどうかとFreeAndNilの利用可能条件は間違いであるとしか言えません。

オブ脳さんの言われている例は、Singletonパターンの作成方法です。
この作業については誰も異論はないと思っています。
>他の人たちがハードコーディングで作成しているのに対して
>>a:=tframe2.Create(self);
が「Mr.XRAY 2006/07/29(土) 16:23:05」の引用だとするとこれは
if not Assigned(a) then a:=tframe2.Create(self);
まで抽出しなくては誤りになります。
そもそも、質問はSingletonパターンの作成方法ではないですよね。
私は相手が初心者である場合、なるべくハードコーディングをすべきだと考えております。
そのほうが理解し易いですからね。

あと、蛇足ですが。
>クラス間の依存関係を、なるべく弱くしないといけません。
Singletonだとインスタンスが自由に作れなくなるんだから依存関係はむしろ強くなるのでは?


とんこつ  2006-09-05 13:00:32  No: 22625

97レス目もうすぐ100レス
寝る前に謝罪。
>>クラス間の依存関係を、なるべく弱くしないといけません。
>Singletonだとインスタンスが自由に作れなくなるんだから依存関係はむしろ強くなるのでは?
そういう意味じゃないですね。ごめんなさい。


zebra  2006-09-05 15:44:31  No: 22626

>オブジェクト指向ではクラス間の依存関係を、なるべく弱くしないといけません。
確かにこの意見は間違っていないと思いますが、今回の話に限って言えば
当てはまらないように思います。
procedure TForm1.Button1Click(Sender: TObject);
begin
  a := TFrame2.Create(self);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  TFrame2.GetInstance(self, 100, 100);
end;

この二つのメソッドにおいて、TForm1とTFrame2の二つのクラス間の結合度は同じだと思います。
クラス間の結合度を弱めるためにはTFrame2という具体的なクラス名を書かずに抽象クラスをかますべきなんじゃないでしょうか?
シングルトンに限って言えば結合度を弱める働きは無いように思うのですがどうなんでしょうか。

あと、シングルトンはインスタンスが一つ以上作成されないことが保障されなければいけません、その為にはコンストラクタをプライベートにして外から呼ばれないようにしなければならないと思うのですが。
Delphiではどのように実現するのでしょうか?

>依存関係が強いとメンテや拡張が大変になります。
>例えば、今Freeを使っても大丈夫だとしても
>プログラムを拡張(継承)してFreeが使えなくなった場合
>二つのクラスを修正しないといけなくなりますね。
Freeが使えなくなる場合とはどのような場合なんでしょうか?
また、その様な場合でもReleaseは使えるのですか?


とんこつにえーと  2006-09-06 06:04:33  No: 22627

とんこつ 2006/09/05(火) 01:02:19 
>オブ脳さんの言われている例は、Singletonパターンの作成方法です。
>この作業については誰も異論はないと思っています。
>>他の人たちがハードコーディングで作成しているのに対して
>>>a:=tframe2.Create(self);
>が「Mr.XRAY 2006/07/29(土) 16:23:05」の引用だとするとこれは
>if not Assigned(a) then a:=tframe2.Create(self);
>まで抽出しなくては誤りになります。
それもハードコーディング


ん?  2006-09-06 07:16:18  No: 22628

遅レスの100ゲット
とりあえず、自分のトコだけ。

> 争点 2006/09/01(金) 03:01:02 
> ん?さん、争点が違うと思いますよ。
ここだけ。

> 結論でてますか? 2006/08/29(火) 20:49:18
より、『争点が(略)であれば、』と、「結論でてますか?さんが言った点が
争点であれば」という仮定であり、『争点は(略)です』と言い切っていません。

繰り返しになりますが、まささんの『モーダレスのフォームは、Releaseで <<必ず>> 解放』が
正しいと << 考える >> ならだけならいいのですが、
正しいと << 言い切る >> のであれば、以下Frameさんの意見は、確実に間違いとなります。

> 『そのフォームまたはその子フォームのイベントハンドラ以外からで、Freeをすることはかまわない
> (By Frame 2006/08/19(土) 17:11:55)』

ならば、『そのフォームまたはその子フォームのイベントハンドラ以外から、
Freeして<<エラーが出る>>ことがある』ことを証明しなくては、まささんの
意見が正しいと言い切るとはできません。

そんなわけで、自分は、争点をまとめたかったわけではなく、
『「〜が正しく、〜が間違い」というコトを言うのであれば、「自分は〜と思う」
のような、感覚的なものでは納得させることはできませんよ。』
というコトを言いたかったわけです。

結論でてますか? 2006/08/29(火) 20:49:18 
> 私はFrameさんの意見が正しいとは書いていませんよね
> 私も、えーとさんと同じく「Free ではなく Release を使うべき」と思っていますから
これから、結論でてますか?さんが、Frameさんが間違っていると思っていると
勝手に考えただけで、間違っているなら、それを証明して見せてくださいと考えたわけです。
もっとも、「Frameさんが間違っている」と言い切っている記述がないことから、
「そんなこと言っていない」と言われたらおしまいですが。

まぎらわしい発言すいませんでした。


オブ脳  2006-09-06 10:23:56  No: 22629

zebra 2006/09/05(火) 06:44:31 
>>オブジェクト指向ではクラス間の依存関係を、なるべく弱くしないといけません。
>確かにこの意見は間違っていないと思いますが、今回の話に限って言えば
>当てはまらないように思います。
>procedure TForm1.Button1Click(Sender: TObject);
>begin
>  a := TFrame2.Create(self);
>end;
>
>procedure TForm1.Button1Click(Sender: TObject);
>begin
>  TFrame2.GetInstance(self, 100, 100);
>end;
>
>この二つのメソッドにおいて、TForm1とTFrame2の二つのクラス間の結合度は同じだと思います。
上の場合、Form1からオブジェクト「a」を操作できますよね、またオブジェクトの作成をForm1が管理していますね。
下の場合はForm1からFrame2へのアクセスは全くできませんし、オブジェクトの生死は知る必要もありません。

>クラス間の結合度を弱めるためにはTFrame2という具体的なクラス名を書かずに抽象クラスをかますべきなんじゃないでしょうか?
そうですね、その方が確か抽象化できますね。

>シングルトンに限って言えば結合度を弱める働きは無いように思うのですがどうなんでしょうか。
相手クラスから、実際にどのクラスが生成されているか分からないと言う意味で抽象化されているとおもいますよ。

>あと、シングルトンはインスタンスが一つ以上作成されないことが保障されなければいけません、その為にはコンストラクタをプライベートにして外から呼ばれないようにしなければならないと思うのですが。
>Delphiではどのように実現するのでしょうか?
私もはっきりとは言えません、Q&Aで出してみたらどうですか?

>>依存関係が強いとメンテや拡張が大変になります。
>>例えば、今Freeを使っても大丈夫だとしても
>>プログラムを拡張(継承)してFreeが使えなくなった場合
>>二つのクラスを修正しないといけなくなりますね。
>Freeが使えなくなる場合とはどのような場合なんでしょうか?
>また、その様な場合でもReleaseは使えるのですか?
Frameさんが発言しているパターンの時ではないですか?
> そのフォームまたはその子フォームのイベントハンドラ以外からで、Freeをすることはかまわない
つまり、Freeの呼出し元がフォームまたは子フォームのイベントハンドラから呼ばれる場合ですね
その場合は、Releaseを使います。


zebra  2006-09-06 16:38:22  No: 22630

>>オブ脳さん
そうですね、確かにクラスの生成が隠蔽化されている時点で若干結合度が下がると考えたほうが良いみたいですね。

ただ細かいことですが、抽象化という言葉の意味がちょっと引っかかりました。
>相手クラスから、実際にどのクラスが生成されているか分からないと言う意味で抽象化されているとおもいますよ
私の考える抽象化とは、文字通りabstractなクラスでありメソッドであると思っています。
例えば、クラスを生成する抽象化されたメソッドとすれば、(Factory Methodだったかな?)があると思いますけど、これはメソッド自身がどのクラス(サブクラス)を生成するのか知らないって事が抽象化なのかなと。
なんか、全然関係ない方向に脱線させてしまってすみません。。

あと、最後の
>>Freeが使えなくなる場合とはどのような場合なんでしょうか?
>>また、その様な場合でもReleaseは使えるのですか?
>Frameさんが発言しているパターンの時ではないですか?
>> そのフォームまたはその子フォームのイベントハンドラ以外からで、Freeをすることはかまわない
>つまり、Freeの呼出し元がフォームまたは子フォームのイベントハンドラから呼ばれる場合ですね
>その場合は、Releaseを使います。
これは、例えばそれぞれ独立したフォームとしてForm1とForm2があるとして、Form2からForm1の解放をしていたとします。(Form1はメインフォームではない)
ここで、オブ脳さんの言われる"プログラムを拡張(継承)してFreeが使えなくなった場合"とはForm2がForm1の子フォームになった場合エラーが発生するってことなんでしょうか?


オブ脳  2006-09-07 07:22:09  No: 22631

zebra 2006/09/06(水) 07:38:22 
>ただ細かいことですが、抽象化という言葉の意味がちょっと引っかかりました。
>>相手クラスから、実際にどのクラスが生成されているか分からないと言う意味で抽象化されているとおもいますよ
>私の考える抽象化とは、文字通りabstractなクラスでありメソッドであると思っています。
>例えば、クラスを生成する抽象化されたメソッドとすれば、(Factory Methodだったかな?)があると思いますけど、これはメソッド自身がどのクラス(サブクラス)を生成するのか知らないって事が抽象化なのかなと。
Abstract Factoryパターンの事ですかね?、確かにそのパターンは抽象化が分かり易いですね。
多分zebraさんが抽象化されていないと思うのは、zebraさんが内部構造(Singleton)を
知っているからだと思います、つまりzebraさんの目線になっています。
これをForm1を中心に考えた場合、Abstract FactoryもSingletonも変わりありませんよね。
クラス(オブジェクト)中心に考える事が大事だと思います。
逆に抽象化反対は具体化ですよね、具体化ではForm1が作成するインスタンスを知っていると言う事になり
つまり「a := TFrame2.Create(self);」これですね、これに比べれば抽象化されている事になると思います。

ん〜なんか言葉遊びみたいになっていますね、上手く説明出来ていませんね
車に例えて簡単に説明すると、カローラ・BMWなど車種が違っても車と抽象化することで運転出来ますね
これが、Abstract Factoryパターンです。次にSingletonパターンですが
これは、カローラはカローラでも新車と中古車の違いですね、これをカローラと抽象化することで運転出来ますよね。

>あと、最後の
>>>Freeが使えなくなる場合とはどのような場合なんでしょうか?
>>>また、その様な場合でもReleaseは使えるのですか?
>>Frameさんが発言しているパターンの時ではないですか?
>>> そのフォームまたはその子フォームのイベントハンドラ以外からで、Freeをすることはかまわない
>>つまり、Freeの呼出し元がフォームまたは子フォームのイベントハンドラから呼ばれる場合ですね
>>その場合は、Releaseを使います。
>これは、例えばそれぞれ独立したフォームとしてForm1とForm2があるとして、Form2からForm1の解放をしていたとします。(Form1はメインフォームではない)
>ここで、オブ脳さんの言われる"プログラムを拡張(継承)してFreeが使えなくなった場合"とはForm2がForm1の子フォームになった場合エラーが発生するってことなんでしょうか?
そうですね、この説明だと分かりにくいですね、すみません。
簡単なソースを書きます。
procedure TForm1.Edit1Change(Sender: TObject);
begin
  if Edit1.Text = '終了' then
  begin
    FreeAndNil(Form2);
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Edit1.Text := '終了';
end;
このままでは、Form2を解放するのにFreeAndNilを使っても大丈夫ですが
この後Form2が拡張されて
procedure TForm2.Button1Click(Sender: TObject);
begin
  Form1.Edit1.Text := '終了';
end;
になったとします、こうなる解放処理の起点が「Form2フォームのイベントハンドラ」になり
Releaseを使わないといけなくなります。


zebra  2006-09-09 05:51:11  No: 22632

抽象化については分かりました。ありがとうございます。

あと、フリーの話しですが、皆さん共通の意見は自殺の時はReleaseを使うって事ですね。

そして、オブ脳さんの意見は他殺の時はFreeで構わないが、拡張されて意図せぬうちに自殺Freeになる可能性があるので、最初から他殺時もReleaseで設計することが望ましいって事ですよね?

これに対して、まささんの意見は他殺Freeでもモードレスではエラーになる事があるから、必ずReleaseを使うべきであると、私は解釈しました。

こう考えると、オブ脳さんがまささんに同意というのは、ちょっと違う気がしました。
逆に、まささんがオブ脳さんに同意するのであれば納得ですが。


けんけん  2006-09-13 22:06:52  No: 22633

すみません、zebraさんに質問なんですが
>zebra 2006/09/02(土) 15:45:11 
>何故かと言うと、例えばForm1からForm2をFreeする場合、必ず安全に解放されることが保証されているからだと思います。これは、Form1もForm2も同じメインスレッドで動いているからじゃないでしょうか?
と書いていますよが、他の発言で
>結論でてますか? 2006/08/27(日) 16:00:37
>エラーになったりならなかったりするのは、多分PostMessageとFreeAndNilのタイミングだと思います。

>とんこつ 2006/08/30(水) 03:14:47 
>>エラーになったりならなかったりするのは、多分PostMessageとFreeAndNilのタイミングだと思います。
>これは正しいですが、今回のエラーはWM_LBUTTONUPが原因ではありません。
と書いています、このエラーになったりならなかったりする原因は
WindowsからのPostMessageとFreeAndNilが非同期で実行されているからですか?
それともPostMessageとPostMessageの間にFreeAndNilが実行されるタイミングがあるからですか?
このあたりが、よく分かりません教えて下さい。


オブ脳  2007-01-21 08:53:14  No: 22634

仕事が忙しかったのでレスが遅れてすみません。
見てもらえるか分りませんが(笑
返事を書きます

>zebra 2006/09/08(金) 20:51:11 
>あと、フリーの話しですが、皆さん共通の意見は自殺の時はReleaseを使うって事ですね。
そうですね。

>そして、オブ脳さんの意見は他殺の時はFreeで構わないが、拡張されて意図せぬうちに自殺Freeになる可能性があるので、最初から他殺時もReleaseで設計することが望ましいって事ですよね?
あくまでもオブジェクト指向で設計した場合の話ですが(^^)

>これに対して、まささんの意見は他殺Freeでもモードレスではエラーになる事があるから、必ずReleaseを使うべきであると、私は解釈しました。
>こう考えると、オブ脳さんがまささんに同意というのは、ちょっと違う気がしました。
>逆に、まささんがオブ脳さんに同意するのであれば納得ですが。
たしかにそうですね、ただFrameさんの発言も疑問ですが
それに私には「他殺Freeでもモードレスではエラーになる事があるから」が正しいか間違っているか分りません。

あと、気になった
>まさ 2006/08/23(水) 15:42:50 
>  Form2は廃棄されましたがメソッドは生きています。
>  この理由は、Delphiの内部構造を理解していないと
>  分からない事なので、分からなくても大丈夫だと思いますが
>  勉強の為に考えて下さい。
まささんの問題を調べてみました。
メソッドは最初から作られ、フィールド(データ)のみがcreate時に作られるですね。
そのオブジェクト毎のフィールドを識別する為に
メソッドに隠れパラメータ:Selfを渡しているんですね。
Selfは知っていましたが、こんな仕組みの為にあったんですね。

>(実話は私も直接Releaseを使いません(Freeも使いません)
>  もっと安全な方法でやっていますが(~_~;))
こっちは、分りませんでした。是非誰か教えれほしいですね。


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

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






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