我有一个函数返回一个OleVariant
,其中包含一个IDispatch
引用计数对象:
class function TGrobber.Make: OleVariant;
begin
Result := (TGrobber.Create as IDispatch);
// Reference count of IDispatch inside Result at this point is 1
end;
函数的结尾,OleVariant
内对象的RefCount正确为1
。
但是,当OleVariant
返回给调用者时,包含的对象突然具有2
的引用计数:
var
grobber: OleVariant;
begin
grobber := TGrobber.Make; // function that returns an OleVariant
// Reference count of IDispatch inside OleVariant is now 2 (wrong)
end;
这是因为Delphi调用了Make函数之后,它调用了VarCopy:
Project2.dpr.147: grobber := TGrobber.Make;
004DA79D 8D55E0 lea edx,[ebp-$20]
004DA7A0 A1DC614D00 mov eax,[$004d61dc]
004DA7A5 E8CAC0FFFF call TGrobber.Make <== Creates the object (refcount 1)
004DA7AA 8D55E0 lea edx,[ebp-$20]
004DA7AD B800444E00 mov eax,$004e4400
004DA7B2 E8B128F5FF call @VarCopy <== Adds an extra reference, loses the old reference
这意味着:
- 编译器正在添加对返回变量的额外引用
- 同时不释放旧的引用
- 或者可替换地根本不调用
@VarCopy
我如何确保德尔福:
- 在制作拷贝后销毁旧的
OleVariant
- 不**复制
OleVariant
,因为它不需要复制
- 不**复制
1条答案
按热度按时间ykejflvf1#
编译器不会丢失“旧”引用。
TGrobber.Make()
的结果首先存储在一个 hidden 局部变量中(位于[ebp-$20]
),然后将其赋给grobber
变量(位于$004e4400
),因此复制。因此refcount为2是正确的。两个变量都将被最终化,refcount减2,当它们在包含例程退出时超出范围时。您的代码 * 有效地 * 完成了以下等效操作: