江湖救急:以下代码运行时出现的内存泄漏,贴出代码,请高手指教! ( 积分: 200 )

  • 主题发起人 主题发起人 yxy2003yxy
  • 开始时间 开始时间
Y

yxy2003yxy

Unregistered / Unconfirmed
GUEST, unregistred user!
以下是代码运行时内存消耗越来越大,最后蓝屏,百思不得其解,问题在哪里?如何解决?急啊,请大侠赐教:
function TForm1.GetContent():string;
var
doc,indoc:IHTMLDocument2;
all,inall:IHTMLElementCollection;
len,i,inlen,k:integer;
item,initem:IHTMLElement;
conHtm,oldImgURL,newImgURL:string;
tmpStream:TFileStream;
myidhttp:TIdHTTP;
begin
conHtm:='';
if Assigned(WebBrowser2)then
begin
doc:=WebBrowser2.document as IHTMLDocument2;//据我测试,这个语句可能是出现内存泄漏,不确定
all:=doc.Get_all;
len:=all.Get_length;
for i:=0 to len-1 do //该循环找到正文元素
begin
item:=all.item(i,varempty) as IHTMLElement;
if or (item.getAttribute('id',0) = 'Content') then
begin
inall:= item.all as IHTMLElementCollection;
inlen:= inall.length ;
for k:=0 to inlen-1 do //该循环找到图片元素
begin
initem:=inall.item(k,varempty) as IHTMLElement;

if initem.Get_tagName = 'IMG'then
begin
intImage:=intImage+1;
oldImgURL:=initem.getAttribute('SRC',0);
intfilename:= intfilename+1;
strpicpath:=DateToStr(date)+IntToStr(intfilename)+'.jpg';
newImgURL:='newsimg/'+strpicpath;
initem.setAttribute('SRC',newImgURL,0);
tmpStream:=TFileStream.Create(newImgURL,fmCreate);

try
idhttp1.Get(oldImgURL,tmpStream); //把图片写到本地
except
on e:exception do
showMessage(e.message);
end;
tmpStream.Free;
end;

end;
conHtm:=item.innerHTML ;
break;
end;
end;
以下是某循环体中对函数的调用
begin
WebBrowser2.Navigate(item.href);
while WebBrowser2.ReadyState <READYSTATE_COMPLETE do
Application.ProcessMessages;
GetContent();
end;
 
以下是代码运行时内存消耗越来越大,最后蓝屏,百思不得其解,问题在哪里?如何解决?急啊,请大侠赐教:
function TForm1.GetContent():string;
var
doc,indoc:IHTMLDocument2;
all,inall:IHTMLElementCollection;
len,i,inlen,k:integer;
item,initem:IHTMLElement;
conHtm,oldImgURL,newImgURL:string;
tmpStream:TFileStream;
myidhttp:TIdHTTP;
begin
conHtm:='';
if Assigned(WebBrowser2)then
begin
doc:=WebBrowser2.document as IHTMLDocument2;//据我测试,这个语句可能是出现内存泄漏,不确定
all:=doc.Get_all;
len:=all.Get_length;
for i:=0 to len-1 do //该循环找到正文元素
begin
item:=all.item(i,varempty) as IHTMLElement;
if or (item.getAttribute('id',0) = 'Content') then
begin
inall:= item.all as IHTMLElementCollection;
inlen:= inall.length ;
for k:=0 to inlen-1 do //该循环找到图片元素
begin
initem:=inall.item(k,varempty) as IHTMLElement;

if initem.Get_tagName = 'IMG'then
begin
intImage:=intImage+1;
oldImgURL:=initem.getAttribute('SRC',0);
intfilename:= intfilename+1;
strpicpath:=DateToStr(date)+IntToStr(intfilename)+'.jpg';
newImgURL:='newsimg/'+strpicpath;
initem.setAttribute('SRC',newImgURL,0);
tmpStream:=TFileStream.Create(newImgURL,fmCreate);

try
idhttp1.Get(oldImgURL,tmpStream); //把图片写到本地
except
on e:exception do
showMessage(e.message);
end;
tmpStream.Free;
end;

end;
conHtm:=item.innerHTML ;
break;
end;
end;
以下是某循环体中对函数的调用
begin
WebBrowser2.Navigate(item.href);
while WebBrowser2.ReadyState <READYSTATE_COMPLETE do
Application.ProcessMessages;
GetContent();
end;
 
首先,你可以用memproof来查到底哪行代码导致内存泄漏!
其次,你可以注释你怀疑的行,以便缩小范围。
最后,建议代码改成:
...
tmpStream:=TFileStream.Create(newImgURL,fmCreate);
try
try
idhttp1.Get(oldImgURL,tmpStream); //把图片写到本地
except
on e:exception do
showMessage(e.message);
end;
finally
tmpStream.Free;
end;
...
我怀疑idhttp1.Get(oldImgURL,tmpStream); 有问题!
 
凡是指针,用完之后最好都自己free掉。
 
谢谢上面的建议,我把GetContent();中的
doc:=WebBrowser2.document as IHTMLDocument2;后面的语句都注释掉了,运行循环体
begin
WebBrowser2.Navigate(item.href);
while WebBrowser2.ReadyState <READYSTATE_COMPLETE do
Application.ProcessMessages;
GetContent();
end;
还是内存泄漏,但是我把GetContent();整个注释掉就没有泄漏现象,所以我怀疑doc:=WebBrowser2.document as IHTMLDocument2;有问题,可是到底是什么原因还是不确定,更不知如何解决,还请多给意见!
 
>>doc,indoc:IHTMLDocument2;
>>all,inall:IHTMLElementCollection;
接口变量用完之后要将其置为nil,否则如果引用计数不为0的话接口对应的对象不释放
 
迷糊一点不迷糊![:D]
 
to迷糊:
按照你的建议,我对GetContent();作了如下修改,把接口用完就nil,问题还是没有解决,随着循环调用次数的增加,消耗的内存还是不停的飙升,是不是还有什么问题:
function TForm1.GetContent():string;
var
doc:IHTMLDocument2;
all,inall:IHTMLElementCollection;
len,i,inlen,k:integer;
item,initem:IHTMLElement;
conHtm,oldImgURL,newImgURL:string;
tmpStream:TFileStream;
myidhttp:TIdHTTP;
begin
conHtm:='';
if Assigned(WebBrowser2)then
begin
doc:=WebBrowser2.document as IHTMLDocument2;
all:=doc.Get_all;
len:=all.Get_length;
for i:=0 to len-1 do //该循环找到正文元素
begin
item:=all.item(i,varempty) as IHTMLElement;
if (item.getAttribute('id',0) = 'p_content') or (item.getAttribute('id',0) = 'zoom') then
begin
inall:= item.all as IHTMLElementCollection;
inlen:= inall.length ;
for k:=0 to inlen-1 do //该循环找到图片元素
begin
initem:=inall.item(k,varempty) as IHTMLElement;
if initem.Get_tagName = 'IMG'then
begin
intImage:=intImage+1;
oldImgURL:=initem.getAttribute('SRC',0);
intfilename:= intfilename+1;

strpicpath:=DateToStr(date)+IntToStr(intfilename)+'.jpg';
newImgURL:='newsimg/'+strpicpath;
initem.setAttribute('SRC',newImgURL,0);
tmpStream:=TFileStream.Create(newImgURL,fmCreate);
myidhttp:= TIdHTTP.Create(nil);
try
myidhttp.Get(oldImgURL,tmpStream); //把图片写到本地
except
//on e:exception do
// showMessage(e.message);
end;
myidhttp.Free ;
tmpStream.Free;
end;
initem :=nil;//释放接口
end;
inall:=nil;//释放接口
conHtm:=item.innerHTML ;
break;
end;
item:=nil;//释放接口
end;
Result := conHtm;
all:= nil;//释放接口
doc :=nil;//释放接口
end;
end;
 
end;
initem :=nil;//释放接口
end;
inall:=nil;//释放接口
conHtm:=item.innerHTML ;
item :=nil;//这里也要释放吧,Break;退出for,下面item:=nil会没有执行。
break;
end;
item:=nil;//释放接口
end;
Result := conHtm;
all:= nil;//释放接口
doc :=nil;//释放接口
end;
end;
//看看能不能对你有帮助...
 
你的问题应该是接口释放的问题。
function TForm1.GetContent():string;这个函数太长了建议你拆分一下这样思路比较清淅。查错也好.
 
接口这东西,好是好,如果没搞好就麻烦。。。
我被这东西折腾了好一阵子.
 
经过逐行排除,可以基本确定是doc:=WebBrowser2.document as IHTMLDocument2;的问题,只是到底是为什么?如何解决呢?
 
如果是doc:=WebBrowser2.document as IHTMLDocument2;的问题,难以理解,因为这个语句
在循环之外……
我觉得在
initem.setAttribute('SRC',newImgURL,0);

initem:=nil;
之间,还应该有释放图形的命令
也许是initem.setAttribute('SRC','',0);
 
首先我确定问题肯定出现在GetContent()中,因为如果不调用该函数就没有泄漏。然后我把该函数注释成如下,发现依然有泄漏,所以只好肯定是doc:=WebBrowser2.document as IHTMLDocument2;问题(把Assigned(WebBrowser2)去掉问题也存在),的确匪夷所思,还请高手出手指点迷津:

function TForm1.GetContent():string;
var
doc:IHTMLDocument2;
all,inall:IHTMLElementCollection;
len,i,inlen,k:integer;
item,initem:IHTMLElement;
conHtm,oldImgURL,newImgURL:string;
tmpStream:TFileStream;
myidhttp:TIdHTTP;
begin
conHtm:='';
if Assigned(WebBrowser2) then
begin
doc:=WebBrowser2.document as IHTMLDocument2;
{.....}
Result := conHtm;
doc :=nil;//释放接口
end;
end;
 
后退
顶部