【发布时间】:2012-06-14 20:53:42
【问题描述】:
我在以下代码中遇到意外的访问冲突错误:
program Project65;
{$APPTYPE CONSOLE}
{$R *.res}
uses
SysUtils;
type
ITest = interface
end;
TTest = class(TInterfacedObject, ITest)
end;
var
p: ^ITest;
begin
GetMem(p, SizeOf(ITest));
p^ := TTest.Create; // AV here
try
finally
p^ := nil;
FreeMem(p);
end;
end.
我知道接口应该以不同的方式使用。但是,我正在研究使用这种方法的遗留代码库。而且我很惊讶地看到保留 SizeOf(ITest) 内存来放置 ITest 是不够的。
现在有趣的是,如果我将第一行更改为
GetMem(p, 21);
比 AV 没了。 (20 字节或更少失败)。对此有何解释?
(我使用的是 Delphi XE2 Update 4 + HotFix)
请不要评论代码有多糟糕或建议如何正确编码。请回答为什么需要保留 21 个字节而不是 SizeOf(ITest) = 4?
【问题讨论】:
-
你的代码看起来很奇怪。为什么需要 "^ITest" 和 GetMem/FreeMem 对? TTest 是 TInterfacedObject 的后代,所以 p 应该只是一个 ITest。它是引用计数的,所以当它超出范围时会自动销毁。无需使用 GetMem/FreeMem。
-
这是使用接口的完全错误的方式。您能解释一下您希望完成什么,以便有人可以为您指明更好的方向吗?
-
1. AV = Access Violation 2. 我知道不应该这样使用。我试图了解我必须使用的遗留代码,这是一种常见的做法。请问各位cmets这段代码有多糟糕,而是尝试回答这个问题?
-
@Ken,我认为您的分析不正确。有时将接口分配给指针以获取弱引用。在此示例中,引用计数正常工作。当接口分配给 p^ 时它会增加,当 p^ 设置为 nil 时它会减少(此时对象被销毁)。
-
我不同意,但我会把这个留给可能比我解释得更好的人。 :-) 很高兴您处理的是遗留代码而不是我。祝你好运。
标签: delphi pointers interface access-violation