前文已经讲过了OleCtrls.pas是如何内存泄漏以及解决方案,但是我们发现该内存泄漏的问题,早已被TEmbeddedWB发现,TEmbeddedWB在Version 14.67.8版本的解决方案并不修改OleCtrls.pas文件,而是每次执行内存泄漏的地方,额外的写上一句_Release;使得引用计数无条件减少1,该方案有点绕路子,而且会与修正问题本质的方案(修改OleCtrls.pas)发生冲突,而且一旦Borland修正了OleCtrls.pas的问题,那么TembeddedWB也就无法正常使用了。更具有讽刺意义的是TEmbeddedWB并没有在所有地方都这样做,那么它也没有解决全部的内存泄漏。
参看部分代码:
procedure TEmbeddedWB.SetUserAgentInt;
var
Control: IOleControl;
begin
if FUserAgent <> FUserAgentInt then
begin
RestoreUserAgentReg;
if DefaultInterface.QueryInterface(IOleControl, Control) = 0 then
with (Application as IOleControl) do
begin
FUserAgentInt := FUserAgent;
Control.OnAmbientPropertyChange(DISPID_AMBIENT_USERAGENT);
//_Release;
end;
end;
end;
于是已经修改OleCtrls.pas的用户将无法正常使用TEmbeddedWB Version 14.67.8 以及附近的版本,在TEmbeddedWB 早期版本例如:14.64是不存在被动修复方案的,所以已经修改OleCtrls.pas的用户可以正常使用TEmbeddedWB 14.64以及附近的版本。
TEmbeddedWB Version 14.67.8我已经作了一个补丁,删除TEmbeddedWB 额外增加的所有_Release调用。这是一个SVN的补丁文件,请看:
Code
Index: EmbeddedWB.pas
===================================================================
--- EmbeddedWB.pas (版本 681)
+++ EmbeddedWB.pas (工作副本)
@@ -2583,7 +2583,7 @@
begin
FUserAgentInt := FUserAgent;
Control.OnAmbientPropertyChange(DISPID_AMBIENT_USERAGENT);
- _Release;
+ //_Release;
end;
end;
end;
Index: EwbCore.pas
===================================================================
--- EwbCore.pas (版本 681)
+++ EwbCore.pas (工作副本)
@@ -1337,7 +1337,7 @@
with (Application as IOleControl) do
begin
OnAmbientPropertyChange(DISPID_AMBIENT_USERMODE);
- _Release;
+ //_Release;
end;
end;
@@ -1374,7 +1374,7 @@
with (Application as IOleControl) do
begin
OnAmbientPropertyChange(DISPID_AMBIENT_DLCONTROL);
- _Release;
+ //_Release;
end;
end;
@@ -1438,7 +1438,7 @@
with (Application as IOleControl) do
begin
OnAmbientPropertyChange(DISPID_AMBIENT_DLCONTROL);
- _Release;
+ //_Release;
end;
end;
Index: EWBTools.pas
===================================================================
--- EWBTools.pas (版本 681)
+++ EWBTools.pas (工作副本)
@@ -1003,7 +1003,7 @@
ScreenImg.SaveToFile(FileName);
Result := True;
finally
- ViewObject._Release;
+ //ViewObject._Release;
end;
except
Result := False;
@@ -3049,7 +3049,7 @@
try
Result := CmdTarget.Exec(PtrGuid, Value1, Value2, vaIn, vaOut);
finally
- CmdTarget._Release;
+ //CmdTarget._Release;
end;
except
end;
Index: IEDownload.pas
===================================================================
--- IEDownload.pas (版本 681)
+++ IEDownload.pas (工作副本)
@@ -6,7 +6,7 @@
// Freeware Component *
// for Delphi by *
// Eran Bodankin *
-// and Per Linds?Larsen *
+// and Per Linds?Larsen *
// *
// *
// Updated versions: *
@@ -895,7 +895,7 @@
Result := S_OK;
FBSCBTimer.Enabled := True; {Timeout timer}
FTimedOut := False;
- Self._Release;
+ //Self._Release;
end;
function TBSCB.OnResponse(dwResponseCode: DWORD; szResponseHeaders,
@@ -1493,9 +1493,9 @@
else if (Assigned(FSender.FOnConnect)) then
FSender.FOnConnect(Self, HR, Registering_new_moniker +
ResponseCodeToStr(HR));
- m_pPrevBSCB._Release;
+ //m_pPrevBSCB._Release;
m_pPrevBSCB := nil;
- FBindCtx._Release;
+ //FBindCtx._Release;
FBindCtx := nil;
Dec(FSender.FRefCount);
end;
@@ -1512,7 +1512,7 @@
FSender.FOnStopBinding(Self, HRESULT, szError);
Result := HRESULT;
- Binding._Release; {Release the binding we called on StartBinding}
+ //Binding._Release; {Release the binding we called on StartBinding}
FSender.FState := sStopped;
if Assigned(FSender.FOnStateChange) then
Index: MenuContext.pas
===================================================================
--- MenuContext.pas (版本 681)
+++ MenuContext.pas (工作副本)
@@ -370,7 +370,7 @@
end;
finally
ShellMalloc.Free(FolderID);
- ShellMalloc._Release;
+ //ShellMalloc._Release;
end;
end;
finally
@@ -416,7 +416,7 @@
FreeMem(ItemPIDLs);
end;
ShellMalloc.Free(FolderID);
- ShellMalloc._Release;
+ //ShellMalloc._Release;
end;
function NextPIDL(PIDL: PItemIDList): PItemIDList;
Index: RichEditBrowser.pas
===================================================================
--- RichEditBrowser.pas (版本 681)
+++ RichEditBrowser.pas (工作副本)
@@ -828,7 +828,7 @@
begin
if IUnknown(Obj) <> nil then
begin
- IUnknown(Obj)._Release;
+ //IUnknown(Obj)._Release;
IUnknown(Obj) := nil;
end;
end;