gpt4 book ai didi

delphi - 利用Delphi的引用计数功能时的内存泄漏

转载 作者:行者123 更新时间:2023-12-03 14:53:36 25 4
gpt4 key购买 nike

下面的代码尝试利用Delphi的引用计数功能。

但是,FullDebugMode 中的 FastMM4 报告 DoStuff1 会出现内存泄漏,而 DoStuff2 则不会。你能帮忙评论一下为什么吗?这两个过程在幕后的行为不应该完全相同吗?

program Project_SO;

{$APPTYPE CONSOLE}

uses
FastMM4,
SysUtils;

type
ITestFunc = interface
['{B3F6D9A7-FC77-40CE-9BBF-C42D7037A596}']
function DoIt(X,Y: Integer): Integer;
end;

TTestFunc = class(TInterfacedObject, ITestFunc)
public
function DoIt(X,Y: Integer): Integer;
end;
TTestFuncClass = class of TTestFunc;

{ TTestFunc }

function TTestFunc.DoIt(X, Y: Integer): Integer;
begin
Result := X + Y;
end;

function DoStuff1(Num1, Num2: Integer; OperationClass: TTestFuncClass): Integer;
begin
Result := ITestFunc(OperationClass.Create).DoIt(Num1, Num2);
end;

function DoStuff2(Num1, Num2: Integer; OperationClass: TTestFuncClass): Integer;
var I: ITestFunc;
begin
I := ITestFunc(OperationClass.Create);
Result := I.DoIt(Num1, Num2);
end;

begin
Writeln(IntToStr(DoStuff1(3, 6, TTestFunc)));
Writeln(IntToStr(DoStuff2(3, 6, TTestFunc)));
end.

最佳答案

Result := ITestFunc(OperationClass.Create).DoIt(Num1, Num2);

此处没有提及所采用的接口(interface)。当将接口(interface)分配给变量或作为按值参数传递时,就会获取引用。事实上,作为按值参数传递,在语义上可以被认为等同于分配给被调用者框架中的局部变量。

但是这段代码中没有任何地方引用。因此,由于没有任何东西引用该接口(interface),因此没有机制可以销毁它。因此发生了泄漏。

var 
I: ITestFunc;
begin
I := ITestFunc(OperationClass.Create);
Result := I.DoIt(Num1, Num2);
end;

在此变体中,进行分配时会获取引用。当局部变量I离开作用域时,它的引用计数减少到零并且实现对象被销毁。

请注意,此处不需要未经检查的强制转换。编译器非常清楚 TTestFunc 实现 ITestFunc 并且您的代码最好应该这样编写:

var 
I: ITestFunc;
begin
I := OperationClass.Create;
Result := I.DoIt(Num1, Num2);
end;

正如评论中所建议的,您可以删除局部变量并使用经过检查的 as 转换:

Result := (OperationClass.Create as ITestFunc).DoIt(Num1, Num2);

实现 as 转换的结果是声明一个隐式局部变量,并将接口(interface)分配给该变量。这意味着引用计数将增加到 1,然后当隐式局部离开作用域时减少到 0。

最后,您的 TTestFunc 类应该有一个虚拟构造函数,因为您打算使用元类实例化它。

关于delphi - 利用Delphi的引用计数功能时的内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33862804/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com