您的代码没有按照您的想法执行。我已经发表了一些评论,试图准确解释正在发生的事情。
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 的处理方式不同吗?
不,我在上面指出的对于从 v1 开始的每个版本的 Delphi 在处理 VCL 和 Windows 时都是相同的。(移动设备上的 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;