Delphi中的forms.pas存在内存泄漏问题吗?

3

你好

我有一个写在 Delphi 2006 中的动态链接库,它在其 uses 子句中包含 forms.pas。

如果我加载该 DLL,然后立即在 for 循环中卸载它,比如说重复进行 10000 次,则内存会慢慢上升。但是,如果我将 Forms.pas 从 DLL 的 uses 子句中移除,则问题就消失了。

这段代码非常简单

以下是我的 DLL 代码:

library Project1;

uses
  Forms;

begin

end.

以下是我的调用应用程序的代码:

procedure TForm1.Button1Click(Sender: TObject);
var
  t_ImportHandle: LongInt;
  t_Index: Integer;
begin
  for t_Index := 0 to 10000 - 1 do
  begin
    t_ImportHandle := LoadLibrary('Project1.dll');
    FreeLibrary(t_ImportHandle);
  end;
 end;

还有其他人能够复制这个问题吗?知道原因并且该如何解决吗?

2个回答

8

TApplication.Create 在 Classes.pas 中使用 MakeObjectInstance 函数。MakeObjectInstance 使用 VirtualAlloc 分配了一个 4KB 的缓冲区,但没有释放它,所以每次加载/卸载 DLL 都会泄漏这么多内存。Andreas Hausladen 曾经在博客中提到过这个问题,但现在似乎已经删除了。可以在 CodeCentral 上找到修复方法,并且也包含在 Andreas 的 VCL Fix Pack 包中。


我也相信这个具体问题在Delphi 2010中得到了解决。 - Ken Bourassa
谢谢,这个补丁确实解决了问题。我在想,除了使用补丁之外,我是否可以编辑VCL(因为我已经这样做来修复其他错误),并在离开MakeObjectInstance之前释放Block?我已经查看了代码,但它将指针分配给不同的变量,所以我无法确定在函数结束时是否安全释放块。 - There is no spoon
1
@Craig:你知道这个问题是否已经提交到QC了吗? - Jeroen Wiert Pluimers
看起来它已经作为3507进入QC,但被标记为“按设计”。正如Ken所说,后来的Delphi版本中有清理块的代码,所以他们必须在某个时候修复了它。 - Zoë Peterson
作为将修复单元添加到dll代码的替代方法,是否有一种外部释放dll消耗的内存的方式?即,您可以安排一个清理未释放的内存的应用程序,当卸载dll时进行清理?有点像垃圾收集器? - There is no spoon
显示剩余6条评论

0

也许这并不是内存泄漏,而是内存管理器碎片化问题。

为什么不尝试使用FastMM高级日志记录功能,看看是否存在内存泄漏。


我已经尝试在DLL和调用应用程序中使用FastMM,但问题仍然存在,fastmm没有报告内存泄漏,实际上它什么都没有报告。我在调用应用程序中创建了一个内存泄漏,fastmm会报告它,但如果我在dll中放置一个内存泄漏,fastmm不会报告它,也许我设置有误? - There is no spoon
无论如何,根据这篇帖子 https://forums.codegear.com/messageview.jspa?messageID=296979 ,这是一个已知的问题,但我无法访问链接 http://qc.codegear.com/wc/qcmain.aspx?d=20712 ,即使我有有效的登录。 - There is no spoon
好的,我已经追踪到问题与在Controls.pas中创建应用程序对象有关。在controls.pas的初始化部分中,调用了InitControls。在这个方法中,全局Application对象被初始化为TApplication的一个实例。如果我注释掉这一行和Application.ShowHint := true这一行,那么问题就消失了。但是,在循环中创建和释放TApplication对象的实例并不会导致内存泄漏。 - There is no spoon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接