Delphi:TADoConnection变量赋值的引用与副本

Delphi:TADoConnection变量赋值的引用与副本,delphi,variable-assignment,adoconnection,Delphi,Variable Assignment,Adoconnection,我想了解Delphi是如何处理作业的。我有一个名为GlobalConn(TADoConnection)的全局连接 我有一个函数,它使用传入的变量进行数据库调用: function MakeDBCall( AConnection : TAdoConnection ) var LocalConn : TAdoConn; begin LocalConn := TAdoConnection.Create(nil); try LocalConn := AConnection

我想了解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:=a连接(在函数内部)时,实际会发生什么情况?引用计数是增加了还是为局部变量分配了一个新副本

  • 释放
    LocalConn
    是否会影响
    GlobalConn

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

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


  • 谢谢

    您的代码没有您认为的功能。我写了一些评论,试图解释到底发生了什么

    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:=a连接(在函数内部)时,实际会发生什么情况?引用计数是增加了还是为局部变量分配了一个新副本
  • 以上都没有

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

  • 释放LocalConn是否会影响GlobalConn
  • 对。它释放了
    a连接
    ,使对它的任何引用无效,可能是您的全局连接实例。(它对您使用
    TADOConnection.Create(nil)
    创建的本地连接没有任何影响;该内存会泄漏,因为您丢弃了可用于释放它的唯一对它的引用

  • 理想情况下,我假设复制比获取连接字符串并分配给局部变量并打开更好(更快)……这是正确的假设吗
  • 可能是,如果你真的在复制,但你不是

  • 这与Delphi 7和XE7-Xe10的处理方式不同吗
  • 不。我在上面指出的是,从v1开始,在处理VCL和Windows时,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;
    

    为什么要这样做,而不仅仅是使用AConnection本身?对TAdoConnection.Create的调用会在堆上创建一个新实例。通过将LocalConn分配给AConnection,然后通过LocalConn.Free对AConnection有效地调用Free,可以有效地丢弃该实例。因此,当您的过程退出时,您已经释放了错误的对象并创建了一个新实例由于丢弃您创建的TAdoConnection对象而导致内存泄漏。它不能像您想象的那样工作,您正在用全局变量覆盖局部变量(从而泄漏本地创建的连接)最后,您将释放全局变量,从而在下次使用全局变量时生成一个AV…@WHOSRDADY:说得好!大家好-谢谢您的评论。让局部变量使用现有变量(全局变量已打开)的“副本”的最佳方式是什么连接-无需打开新连接?当我说“打开”意味着创建一个新的连接对象并设置connectionstring然后打开时。我的假设是多次打开连接会产生一些延迟时间。感谢您提供的信息和建议。我的困惑是因为没有意识到当使用了信号“操作员”。这是一个指向Embarcadero人员的链接,增加了我的理解:。