在设置为 nil 的对象引用上调用 Free 不应该在每次调用时都会抛出访问冲突吗?
我从单元 DBXCommon.pas
(在 Delphi XE 中)收到访问冲突。当我查看代码时,我看到如下内容(在感叹号处):
function TDBXConnectionFactory.GetConnection(const DBXContext: TDBXContext;
const ConnectionProperties: TDBXProperties): TDBXConnection;
var
ConnectionBuilder: TDBXConnectionBuilder;
DelegatePath: TDBXDelegateItem;
Connection: TDBXConnection;
CombinedProperties: TDBXProperties;
begin
//...
ConnectionBuilder := TDBXConnectionBuilder.Create;
Connection := nil;
try
//..lots of setting ConnectionBuilder properties
ConnectionBuilder.FInputPassword := CombinedProperties[TDBXPropertyNames.Password];
Connection := ConnectionBuilder.CreateConnection;
Connection.Open;
Result := Connection;
!! Connection := nil;
finally
!! Connection.Free;
ConnectionBuilder.Free;
end;
end;
但我在 DBXCommon.pas
中看到更多类似这样的构造(首先分配 Nil,然后分配 Free)。这是我不知道的一些构造,还是这真的导致每次调用这段代码时发生访问冲突?
I'm getting access violations from the unit DBXCommon.pas
(in Delphi XE). When I look at the code I see things like the following (at the exclamation marks):
function TDBXConnectionFactory.GetConnection(const DBXContext: TDBXContext;
const ConnectionProperties: TDBXProperties): TDBXConnection;
var
ConnectionBuilder: TDBXConnectionBuilder;
DelegatePath: TDBXDelegateItem;
Connection: TDBXConnection;
CombinedProperties: TDBXProperties;
begin
//...
ConnectionBuilder := TDBXConnectionBuilder.Create;
Connection := nil;
try
//..lots of setting ConnectionBuilder properties
ConnectionBuilder.FInputPassword := CombinedProperties[TDBXPropertyNames.Password];
Connection := ConnectionBuilder.CreateConnection;
Connection.Open;
Result := Connection;
!! Connection := nil;
finally
!! Connection.Free;
ConnectionBuilder.Free;
end;
end;
But I see constructs like this (first assign Nil, then a Free) much more in DBXCommon.pas
. Is this some construct I do not know, or is this really causing access violation every time this piece of code is called?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
对空引用调用
Free
始终是安全的。查看TObject.Free
的实现来了解原因。此代码是工厂函数的示例。它的工作是创建一个类的新实例,但如果失败,它需要确保在抛出异常时不会泄漏半创建的实例,因此它调用
Free
。当确定它会成功时,它将结果的所有权转移给调用者。它仍然调用Free
,但如果它已经转移了所有权,那么它最终会在空引用上调用Free
,并且不会造成任何损害。这段代码就是转移所有权的:我编写工厂函数的方式将消除单独的
Connection
变量。我会直接在Result
中构造结果,但如果出现异常则释放它,如下所示:这具有相同的效果。
Calling
Free
on a null reference is always safe. Go look in the implementation ofTObject.Free
to see why.This code is an example of a factory function. Its job is to create a new instance of a class, but if it fails, it needs to make sure it doesn't leak a half-created instance when it throws an exception, so it calls
Free
. When it's sure it's going to succeed, it transfers ownership of the result to the caller. It still callsFree
, but if it's already transfered ownership, then it ends up callingFree
on a null reference, and there's no harm done. This code is what transfers ownership:The way I would write a factory function would do away with the separate
Connection
variable. I'd construct the result directly inResult
, but free it if there were an exception, like this:That has the same effect.
在
nil
引用上调用Free
是安全的,因为它会检查Self <> 的实现。 nil
在调用Destroy
之前。请参阅Embarcadero 论坛中 Allen Bauer 的解释引入了 TObject.Free
。我在这里只引用相关的引用:It is safe to call
Free
onnil
reference as it's implementation checks forSelf <> nil
before callingDestroy
. See Allen Bauer's explanation in Embarcadero forum whyTObject.Free
was introduced. I include only the relevant quote here:TObject.Free
基本上实现为if Self <> nil 然后 Destroy
,因此上面的代码不应引发任何异常。TObject.Free
is basically implemented asif Self <> nil then Destroy
, so the code above should not raise any exception.