TStreamAdapterのメモリーリークの防止は

解決


吉田  2009-06-18 09:04:20  No: 34828

みなさんまたまた教えて頂きたいことが置きました。
TWebBrowserの表示中の画面のソースを取得したいので
次のようなサンプルを見つけてそのまま使っていますが
チェッカーをかけると
推定クラス名:TStreamAdapter)でメモリーリーリークしているとでるのです。
いろいろやっているのですが、対処法を教えて頂けませんか。
function TForm1.GetSource: String;
var
  Doc: IHTMLDocument2;
  Persist: IPersistStream;
  Mem: TStringStream;
begin
  if (Form1.PageControl1.ActivePage as TTabSheetEx).EmbeddedWB1.Document = nil then
    Exit;
  Mem := TStringStream.Create('');
  try
    Doc := (Form1.PageControl1.ActivePage as TTabSheetEx).EmbeddedWB1.Document as IHTMLDocument2;
    if Doc = nil then  Exit;
    Persist := Doc as IPersistStreamInit;
    Persist.Save(TStreamAdapter.Create(Mem), True);
    Result := Mem.DataString;
  finally
    Mem.Free;
  end;
end;


吉田  2009-06-18 09:07:07  No: 34829

すみません。自己レスです。
自分がいじくり回した方を送りましたので、下記がオリジナルです。

function TForm1.GetSource: String;
var
  Doc: IHTMLDocument2;
  Persist: IPersistStream;
  Mem: TStringStream;
begin
  if WebBrowser1.Document = nil then
    Exit;
  Mem := TStringStream.Create('');
  try
    Doc := WebBrowser1.Document as IHTMLDocument2;
    if Doc = nil then
      Exit;
    Persist := Doc as IPersistStreamInit;
    Persist.Save(TStreamAdapter.Create(Mem), True);
    Result := Mem.DataString;
  finally
    Mem.Free;
  end;
end;


KHE00221  2009-06-18 13:04:00  No: 34830

TStreamAdapterが開放されてないから?


吉田  2009-06-18 19:00:10  No: 34831

KHE00221さん有り難うございます。
すみませんがまだサンプルコードを理解しているわけではありません。
Mem: TStringStream;と定義されていますが
TStreamAdapterという単語は始めてみます。
これの解放とはどのようにすればいいのでしょうか。
StreamAdapter.free;などとは許してくれないものですから。
よろしくお願いいたします。


KHE00221  2009-06-18 19:33:00  No: 34832

こう

function TForm1.GetSource: String;
var
  Doc: IHTMLDocument2;
  Persist: IPersistStream;
  Mem: TStringStream;
  SM : TStreamAdapter;
begin
  if WebBrowser1.Document = nil then
    Exit;

  Mem := TStringStream.Create('');
  SM := TStreamAdapter.Create(Mem);
  try
    Doc := WebBrowser1.Document as IHTMLDocument2;
    if Doc = nil then
      Exit;
    Persist := Doc as IPersistStreamInit;
    Persist.Save(SM, True);
    Result := Mem.DataString;
  finally
    SM.Free;
    Mem.Free;
  end;

end;


吉田  2009-06-18 20:19:00  No: 34833

KHE00221さん、何度もお手数おかけして申し訳ありませんでした。
旨く解決できました。
TStreamAdapterの解放の件は難しく
初心者がヘルプを読んでも理解できるレベルではありません。
ネットでもいろいろやりとりされているようですが
理解できるページを発見できませんでした。
有り難うございました。m(_ _)m


ん〜・・・  2009-06-18 22:10:39  No: 34834

> TStreamAdapterの解放の件は難しく
> 初心者がヘルプを読んでも理解できるレベルではありません。
Create したら Free する。
ただそれだけの基本的なことだよ。
サンプルでは、 TStringStreamをCreateしたものを、変数Memに入れて、最後はFreeしてるでしょ?


吉田  2009-06-18 23:01:24  No: 34835

ん〜・・・さんご指導有り難うございます。
私も当初TStringStreamをCreateしたものと考えていました。
よく見るとTStringStreamで少し違う見たこと無いコードだなと思いました。
それでは、TStreamAdapter.Create(Mem)を破棄すればいいのかなと
思っても、これをフリーにする方法が解りませんでした。
TStreamAdapter.Create(Mem).Free; などとしたりして。
StringList:=TStringList.Create;
finally  StringList.Free;  end;
のようなレベルしか知らない初心者には見当が付きません。
まして、サンプルもおそらく熟練者の書かれたコードだろうと想像しますから、どこが悪いのだろうとますます解らないです。
ご存じの方からすれば簡単なことかもしれませんが、
SM := TStreamAdapter.Create(Mem);
SM.Free;
このような手法があるのは一つ勉強になりました。
有り難うございました。


Mr.XRAY  2009-06-19 01:00:58  No: 34836

>このような手法があるのは一つ勉強になりました。

手法というより,CreateしてFreeするのが基本ですね.
実行時に生成したものは,ほとんどそうです.

CreateのOwnerが自分自身の時は別です.
この掲示板でも何回も(何十回?)も出てくる文章なので,くどいですが.

忙しいでしょうが,ご自分が質問したスレッドだけではなく,
たまには,他の方のスレッドにも目を通しておくといいかも知れません.
参考になる記事がある場合があります.


Mr.XRAY  2009-06-19 01:06:06  No: 34837

失礼.

>CreateのOwnerが自分自身の時は別です.

CreateのOwnerが解放,破棄する場合等は別です.


ミスには偽装?  2009-06-19 01:50:30  No: 34838

>チェッカーをかけると
>推定クラス名:TStreamAdapter)でメモリーリーリークしているとでるのです。

それはメモリーチェッカーがミスをしてるのでは?
TStreamAdapterは、TInterfacedObjectクラスを継承しているので、
破棄は自動的に行われて、自分で破棄する必要は無いはず。

var
  sa: TStreamAdapter;
begin
  sa := TStreamAdapter.Create(Mem, soReference);
のように、TStreamAdapterを実装するのではなく、

var
  sa: IStream;
begin
  sa := TStreamAdapter.Create(Mem, soReference) as IStream;
のように偽装してやれば、メモリーチェッカーもミスしない?


吉田  2009-06-19 03:19:01  No: 34839

ミスには偽装?さん有り難うございました。
おっしゃるとおり
下記の通りやったらFreeしなくてもリークしませんでした。
var
  sa: IStream;
begin
  sa := TStreamAdapter.Create(Mem, soReference) as IStream;
IStreamの変数に代入して処理する手法も勉強になります。
KHE00221さんのコードは少し理解できるようなのでこの方法でやってみます。
有り難うございました。 
では。


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

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






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