我试图了解Delphi如何处理任务。我有一个名为GlobalConn
(TADoConnection
)...
我有一个使用传入的变量进行数据库调用的函数:
function MakeDBCall( AConnection : TAdoConnection )
var LocalConn : TAdoConn;
begin
LocalConn := TAdoConnection.Create(nil);
try
LocalConn := AConnection
///create the table and perform action using the LocalConn
finally
LocalConn.free;
end;
end;
将使用MakeDbCall
(GlobalConn
);
LocalConn := AConnection
(函数内部)实际发生了什么?引用计数是增加还是新副本分配给局部变量?
释放LocalConn
会影响GlobalConn
吗?
理想情况下,我认为制作副本比获取连接字符串更好(更快)并分配给局部变量并打开......这是正确的假设吗?
这与Delphi 7和XE7-Xe10的处理方式有何不同?
感谢
答案 0 :(得分:3)
您的代码没有按照您的想法执行。我已经提出了一些意见,试图解释究竟发生了什么。
function MakeDBCall( AConnection : TAdoConnection )
var
LocalConn : TAdoConn;
begin
// This creates a brand new ADO connection.
LocalConn := TAdoConnection.Create(nil);
try
// This line discards the connection you've just created,
// orphaning it (leaking the memory), and sets LocalConn
// to point to the object passed in as AConnection.
LocalConn := AConnection
///create the table and perform action using the LocalConn
finally
// This line frees AConnection, making your global variable invalid
LocalConn.free;
end;
end;
所以直接处理你提出的问题:
- LocalConn:= AConnection(函数内部)实际发生了什么?引用计数是增加还是新副本分配给本地变量?
醇>
以上都不是。
分配会丢弃您刚刚创建的全新连接,泄漏已分配的内存,LocalConn
成为指向AConnection
的新变量,而不是副本。 TADOConnection
不是接口,因此不受引用计数的影响。没有分配新副本 - LocalConn
只是指向您传递给函数的连接实例的另一个变量。
- 释放LocalConn会影响GlobalConn吗?
醇>
是。它释放AConnection
,使得对它的任何引用都无效,可能是你的全局连接实例。 (它对您使用TADOConnection.Create(nil)
创建的本地连接没有任何作用;该内存被泄露,因为您放弃了可用于释放它的唯一引用。
- 理想情况下,我认为制作副本比获取连接字符串更好(更快)并分配给局部变量并打开......这是正确的假设吗?
醇>
可能是,如果事实上你正在复制,但你不是。
- 这是否与Delphi 7和XE7-Xe10不同?
醇>
没有。在处理VCL和Windows时,我在上面提到的从v1开始的每个版本的Delphi都是一样的。 (移动设备上的FMX改变了一些东西,但它不会改变你仍然错误地释放全局对象的事实。)
如果TADOConnection
实际上实现了Assign
方法,则可以使用它。然而,从文档中不清楚它是否已实现;文档链接到TPersistent.Assign
。您可以查看您实际使用的Delphi版本的来源(我在这台笔记本电脑上没有D2007),看它是否已实现。如果是,您可以使用以下内容:
LocalConn := TADOConnection.Create(nil);
try
LocalConn.Assign(AConnection);
// Use LocalConn
finally
LocalConn.Free; // Frees the local copy
end;