德尔福:参考VS副本的TADoConnection变量分配
我想了解德尔福如何处理任务。我有一个被称为GlobalConn
(TADoConnection
)全球连接...德尔福:参考VS副本的TADoConnection变量分配
我已经使得使用变量数据库调用的函数传递参数:使用MakeDbCall
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;
的调用将进行(GlobalConn
);
LocalConn := AConnection
(函数内部)实际发生了什么?引用计数是增加还是分配给局部变量的新副本?释放
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:= AConnection(在函数内部)?引用计数是增加还是分配给局部变量的新副本?
以上都不是。
该分配放弃了您刚刚创建的全新连接,泄漏了分配的内存,并且LocalConn
成为指向AConnection
的新变量,而不是副本。 TADOConnection
不是一个接口,因此不受引用计数的限制。没有分配新副本 - LocalConn
只是另一个指向您传递给函数的连接实例的变量。
- 释放LocalConn是否影响GlobalConn?
是的。它释放了AConnection
,使其对它的任何引用无效,大概是您的全局连接实例。 (它对你使用TADOConnection.Create(nil)
创建的本地连接没有任何影响;该内存被泄露,因为你丢弃了可以用来释放它的唯一引用。
开始=“3”>
- 理想我假定制作副本是比服用连接字符串和分配给局部变量和开口更好(较快)...这是一个正确推定?
它可能是,如果事实上你做一个副本,但你不是。
- 这是否与Delphi 7和XE7-Xe10不同?
号我上面指出的是从V1起与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;
感谢您的信息和建议。我的困惑是基于没有意识到使用赋值“操作符”时会发生什么。这是一个链接到Embarcadero人加入我的理解:http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/delphivclwin32/Classes_TPersistent_Assign.html。 –
你为什么这样做,而不是只使用AConnection本身?您对TAdoConnection.Create的调用会在堆上创建一个新实例。通过将LocalConn分配给AConnection,然后通过LocalConn.Free有效地调用AConnection上的Free,可以有效地放弃这一点。因此,当程序退出时,您已经释放了错误的对象,并通过丢弃所创建的TAdoConnection对象来创建内存泄漏。 – MartynA
它不会像你想像的那样工作,而是用全局覆盖局部变量(并因此泄漏本地创建的连接),最后释放全局变量,导致下次打算使用AV时全球变... – whosrdaddy
@whosrdaddy:好吧! – MartynA