メモリの解放(?)の要不要に関して。

解決


SEPR  2010-09-15 03:46:36  No: 39159

メモリの解放(?)について。

「解放」が必要な場合と(あるならば)不要な場合との判断が付かず、
いつも良く分からないままにアプリを作ってしまっています。
どのように判断したら良いのでしょうか。

例えば、
下記はタイマーで5秒ごとに実行するプログラムですが、
この場合、(例えば「WinHnd」などの)解放は必要なのでしょうか?

どなたかアドバイスをお願い致します。

//---------------------------------------
procedure TForm1.Timer1Timer(Sender: TObject);
begin
  MesCheck;
end;

procedure TForm1.MesCheck;
var
  WinHnd   :   Integer;
  WinHndSub   :   Integer;
begin
  WinHnd      :=   FindWindow('HogehogeDialogClass', nil);
  if  WinHnd  >    0   then
  begin
    WinHndSub      :=   FindWindow(nil, PWideChar('Hogehogeメッセージ'));
    SendMessage(WinHndSub, WM_CLOSE, 0, 0);
  end;
end;


通りすがり  2010-09-15 06:24:27  No: 39160

変数自体の解放は必要無いです。
Delphiが勝手にやってくれると思って良いと思います。

また、FindWindowの返り値は解放する必要ないです。

---

他の場合では、変数自体の解放は必要なくても、その変数が指し示す何かが、関数内で確保されたとするなら、それの解放は必要となる場合もあります。

開発環境のバージョンによると思うんですが、例えば、エディタで、CTRL押しながらFindWindowをクリックして、ソースを辿ります。
で、その関数のが何をしているのか確認するのが安全かと思います。
function test: integer;
begin
    Result:= integer(TStringList.Create);
end;
こういうのは滅多に無いと思うんですが無いわけでは有りません。
確認しない事にはわかりません。

ちなみに、FindWindowはAPIなので、ソースを辿っても中身はありません。

こういう場合は MSDNに精通するか FindWindowにカーソルを合わせて、F1キーを押してヘルプを読むしか無いです。
初めて使うAPI関数などの場合は、このように仕様を調べたほうが良いでしょう。

開放が必要な場合は、ヘルプの下のほうに関連するAPI関数の一覧があって、開放するための関数が含まれているはずなので、その関数名のリンクを辿って読み進める事により、開放の必要性を予想できるわけです。


var
  dc:hdc; //longword
begin
  dc:=GetDC(Handle);
  ReleaseDC(Handle,dc);  //GetDCとセットでAPIのヘルプに書いてある
end;

ただし、解放関数があっても、用途によっては解放してはならない場合や、タイミングが指定されている場合もあります。

とはいえ、変数である dc 自体を開放しているわけではないので、dc は開放されていません。
開放しているのは dc が示していた デバイスコンテキストのハンドルで、変数 dc ではないのです。
なので、dc自体の開放は必要ありません。

あえて変数の確保と解放をやろうとすると、以下のようになります。
var
  dc: pLongword;
begin
  GetMem(dc,SizeOf(Longword));
  dc^:=GetDC(Handle);
  ReleaseDC(Handle,dc);
  FreeMem(dc,SizeOf(Longword));
end;

また、オブジェクトのインスタンスも、どこかしらで解放が必要です。
忘れるとメモリーリークになります。
(TComponentを継承した CreateでOwnerを指定するオブジェクトはOwnerがDestroyCompomentsというメソッドを持っていてデストラクタで勝手に呼び出して解放しくれますが、明示的に解放しても問題は有りません。)

・オブジェクトの解放の例
function test: TObject;
begin
  Result:= TStringList.Create;
end;

var
 s: TObject;
begin
 s:= test;
 s.Free; //s が 指し示すオブジェクトを解放。
end;

変数 s 自体は解放の必要が無いので解放していません。

他にも色々有りますが、今回は関係ないので書かないでおきます。

シンプルな質問のはずなのに、回答しようとすると、いろいろあって大変ですね。


SEPR  2010-09-16 03:40:28  No: 39161

通りすがりなのに...
とても詳しい説明ありがとうございました。(^^)

・Ctrl押しながらクリックでソースをたぐれる
・解放する関数が含まれていたらソースをたぐり必要性を予想
・Createしたオブジェクト(オブジェクトのインスタンスと言う?)は解放する

少し糸口が見えたように思います。
とても参考になりました。
ありがとうございました。


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

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






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