1

我试图了解 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) 进行调用;

  1. 什么时候LocalConn := AConnection(在函数内部)实际发生了什么?是引用计数增加还是分配给局部变量的新副本?

  2. 释放LocalConn影响GlobalConn

  3. 理想情况下,我认为制作副本比获取连接字符串并分配给局部变量并打开......这是一个正确的假设吗?

  4. 这与 Delphi 7 和 XE7-Xe10 的处理方式不同吗?

谢谢

4

1 回答 1

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;

因此,要处理您直接提出的问题:

  1. 当 LocalConn := AConnection (在函数内部)时实际发生了什么?是引用计数增加还是分配给局部变量的新副本?

以上都不是。

该分配丢弃了您刚刚创建的全新连接,泄漏了分配的内存,并LocalConn成为指向 的新变量,AConnection而不是副本。TADOConnection不是接口,因此不受引用计数的影响。没有分配新副本 -LocalConn只是另一个指向您传递给函数的连接实例的变量。

  1. 释放 LocalConn 会影响 GlobalConn 吗?

是的。它释放AConnection,使对它的任何引用无效,大概是您的全局连接实例。(它对您创建的本地连接没有任何作用TADOConnection.Create(nil);该内存已泄漏,因为您丢弃了对它的唯一引用,该引用可用于释放它。

  1. 理想情况下,我认为制作副本比获取连接字符串并分配给局部变量并打开......这是一个正确的假设吗?

可能是,如果实际上您正在制作副本,但您不是。

  1. 这与 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;
于 2016-09-23T23:07:22.493 回答