如何为接口对象注册预期的内存泄漏

3

是否可以使用RegisterExpectedMemoryLeak过程来注册接口?

我声明了一个私有字段:

FDragDropTarget: IDropTarget;

我随后创建了这个实例,并尝试为该对象注册已知的内存泄漏:
  FDragDropTarget := TDropTarget.Create(lcMain.Handle, FDragDrop);
  RegisterExpectedMemoryLeak(FDragDropTarget);

然而,我收到一个编译器错误,指出存在不兼容的类型:'Pointer'和'IDropTarget'。 对我来说,我的接口实例无论如何都是指针?所以我能做到这一点吗?这是通过我在.dpr文件中拥有的ReportMemoryLeaksOnShutdown := True语句报告的。
begin
  ReportMemoryLeaksOnShutdown := True;
  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  Application.CreateForm(TForm2, Form2);
  Application.Run;
end.

TDropTarget是我对IDropTarget接口的实现:

  TDropTarget = class(TInterfacedObject, IDropTarget)
  ...
  end;

谢谢

2个回答

5

泄漏的不是接口,而是实现它的对象。因此,我认为需要注册的就是该对象:

FDragDropTargetObj: TDropTarget;
FDragDropTarget: DropTarget;


FDragDropTargetObj := TDropTarget.Create(lcMain.Handle, FDragDrop); 
FDragDropTarget := FDragDropTargetObj;
RegisterExpectedMemoryLeak(FDragDropTargetObj);

谢谢。我想到了类型转换,但不确定旧的“不要混合接口和对象引用”的规则,但考虑到你和David都提供了基本相同的解决方案,那肯定是正确的! - Jason
是的。你说得没错,不要混合使用……但在这种情况下,你不需要这样做。你所做的只是注册一个匿名指针到一块内存中,以便让内存管理器检查该内存是否被释放。它实际上与对象或接口无关。这是那些他们从来不告诉你的例外之一。 ;) - GolezTrol

2

您需要注册实现对象,而不是接口,因为这是泄漏的东西:

RegisterExpectedMemoryLeak(FDragDropTarget as TObject);

这个对象发生泄漏表明你的引用计数出了问题。我建议你修复潜在问题,而不是压制它。

这个字段应该声明为“TDropTarget”才能使其工作。但是那样就没有问题了... - Sertac Akyuz
2
@Sertac 为什么这不行呢?接口可以转换为实现对象。 - David Heffernan
@sertac 不用担心。接口泄漏肯定有问题。 - David Heffernan
是的,内存泄漏应该被修复,但现在它只是一个小问题,我只是对于这个特定的场景想要隐藏信息。谢谢。 - Jason
1
很容易找到泄漏的原因。你的代码在某种程度上会对对象进行额外的引用,而这些引用从未被释放。通过使用TInterfacedObject实现中相同的代码,在TDropTarget上重新实现IInterface。然后在TDropTarget._AddRefTDropTarget._Release上设置断点。这将揭示额外引用的原因。 - David Heffernan

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