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

解決


吉田  2009-06-18 00:04:20  No: 34828  IP: 192.*.*.*

みなさんまたまた教えて頂きたいことが置きました。
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 00:07:07  No: 34829  IP: 192.*.*.*

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

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 04:04:00  No: 34830  IP: 192.*.*.*

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

編集 削除
吉田  2009-06-18 10:00:10  No: 34831  IP: 192.*.*.*

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

編集 削除
KHE00221  2009-06-18 10:33:00  No: 34832  IP: 192.*.*.*

こう

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 11:19:00  No: 34833  IP: 192.*.*.*

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

編集 削除
ん〜・・・  2009-06-18 13:10:39  No: 34834  IP: 192.*.*.*

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

編集 削除
吉田  2009-06-18 14:01:24  No: 34835  IP: 192.*.*.*

ん〜・・・さんご指導有り難うございます。
私も当初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-18 16:00:58  No: 34836  IP: 192.*.*.*

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

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

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

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

編集 削除
Mr.XRAY  2009-06-18 16:06:06  No: 34837  IP: 192.*.*.*

失礼.

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

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

編集 削除
ミスには偽装?  2009-06-18 16:50:30  No: 34838  IP: 192.*.*.*

>チェッカーをかけると
>推定クラス名: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-18 18:19:01  No: 34839  IP: 192.*.*.*

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

編集 削除