みなさんまたまた教えて頂きたいことが置きました。
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;
すみません。自己レスです。
自分がいじくり回した方を送りましたので、下記がオリジナルです。
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;
TStreamAdapterが開放されてないから?
KHE00221さん有り難うございます。
すみませんがまだサンプルコードを理解しているわけではありません。
Mem: TStringStream;と定義されていますが
TStreamAdapterという単語は始めてみます。
これの解放とはどのようにすればいいのでしょうか。
StreamAdapter.free;などとは許してくれないものですから。
よろしくお願いいたします。
こう
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;
KHE00221さん、何度もお手数おかけして申し訳ありませんでした。
旨く解決できました。
TStreamAdapterの解放の件は難しく
初心者がヘルプを読んでも理解できるレベルではありません。
ネットでもいろいろやりとりされているようですが
理解できるページを発見できませんでした。
有り難うございました。m(_ _)m
> TStreamAdapterの解放の件は難しく
> 初心者がヘルプを読んでも理解できるレベルではありません。
Create したら Free する。
ただそれだけの基本的なことだよ。
サンプルでは、 TStringStreamをCreateしたものを、変数Memに入れて、最後はFreeしてるでしょ?
ん〜・・・さんご指導有り難うございます。
私も当初TStringStreamをCreateしたものと考えていました。
よく見るとTStringStreamで少し違う見たこと無いコードだなと思いました。
それでは、TStreamAdapter.Create(Mem)を破棄すればいいのかなと
思っても、これをフリーにする方法が解りませんでした。
TStreamAdapter.Create(Mem).Free; などとしたりして。
StringList:=TStringList.Create;
finally StringList.Free; end;
のようなレベルしか知らない初心者には見当が付きません。
まして、サンプルもおそらく熟練者の書かれたコードだろうと想像しますから、どこが悪いのだろうとますます解らないです。
ご存じの方からすれば簡単なことかもしれませんが、
SM := TStreamAdapter.Create(Mem);
SM.Free;
このような手法があるのは一つ勉強になりました。
有り難うございました。
>このような手法があるのは一つ勉強になりました。
手法というより,CreateしてFreeするのが基本ですね.
実行時に生成したものは,ほとんどそうです.
CreateのOwnerが自分自身の時は別です.
この掲示板でも何回も(何十回?)も出てくる文章なので,くどいですが.
忙しいでしょうが,ご自分が質問したスレッドだけではなく,
たまには,他の方のスレッドにも目を通しておくといいかも知れません.
参考になる記事がある場合があります.
失礼.
>CreateのOwnerが自分自身の時は別です.
CreateのOwnerが解放,破棄する場合等は別です.
>チェッカーをかけると
>推定クラス名:TStreamAdapter)でメモリーリーリークしているとでるのです。
それはメモリーチェッカーがミスをしてるのでは?
TStreamAdapterは、TInterfacedObjectクラスを継承しているので、
破棄は自動的に行われて、自分で破棄する必要は無いはず。
var
sa: TStreamAdapter;
begin
sa := TStreamAdapter.Create(Mem, soReference);
のように、TStreamAdapterを実装するのではなく、
var
sa: IStream;
begin
sa := TStreamAdapter.Create(Mem, soReference) as IStream;
のように偽装してやれば、メモリーチェッカーもミスしない?
ミスには偽装?さん有り難うございました。
おっしゃるとおり
下記の通りやったらFreeしなくてもリークしませんでした。
var
sa: IStream;
begin
sa := TStreamAdapter.Create(Mem, soReference) as IStream;
IStreamの変数に代入して処理する手法も勉強になります。
KHE00221さんのコードは少し理解できるようなのでこの方法でやってみます。
有り難うございました。
では。
ツイート | ![]() |