您的代碼不會做你認爲它。我已經提出了一些評論,試圖解釋到底發生了什麼。
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起與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;
你爲什麼這樣做,而不是隻使用AConnection本身?您對TAdoConnection.Create的調用會在堆上創建一個新實例。通過將LocalConn分配給AConnection,然後通過LocalConn.Free有效地調用AConnection上的Free,可以有效地放棄這一點。因此,當程序退出時,您已經釋放了錯誤的對象,並通過丟棄所創建的TAdoConnection對象來創建內存泄漏。 – MartynA
它不會像你想像的那樣工作,而是用全局覆蓋局部變量(並因此泄漏本地創建的連接),最後釋放全局變量,導致下次打算使用AV時全球變... – whosrdaddy
@whosrdaddy:好吧! – MartynA