2008-08-27 74 views
8

在我的一個VB6表單中,我創建了幾個其他Form對象並將它們存儲在成員變量中。什麼時候我必須在VB6中設置一個變量爲「Nothing」?

Private m_frm1 as MyForm 
Private m_frm2 as MyForm 

// Later... 
Set m_frm1 = New MyForm 
Set m_frm2 = New MyForm 

我注意到,當這個(父)形式被創建和銷燬時,我正在泄漏內存。我是否需要將這些成員變量分配到Form_Unload()中的Nothing

一般來說,什麼時候需要?

解決:這個特定的內存泄漏是當我在表單上做了Unload而不是當我將表單設置爲Nothing時修復的。我設法刪除了一些其他的內存泄漏,通過明確設置類模塊的一些實例爲Nothing

回答

5

@Matt Dillard - 將這些設置爲無法解決您的內存泄漏?

VB6沒有正式的垃圾收集器,更多的是@Konrad Rudolph所說的。

實際上,在窗體上調用unload似乎是確保主窗體清理並確保每個子窗體清理其操作的最佳方法。

我測試了一個空白項目和兩個空白表單。

Private Sub Form_Load() 
    Dim frm As Form2 
    Set frm = New Form2 
    frm.Show 
    Set frm = Nothing 
End Sub 

運行後,兩個窗體都可見。將frm設置爲無效......沒有什麼。

在設置frm爲空之後,唯一對此表單打開的句柄是通過引用。

Unload Forms(1) 

我看到了問題嗎?

  • 約什
2

嚴格來說從來沒有,但它給垃圾收集器一個強大的暗示來清理事情。

作爲一項規則:每次完成創建對象時都會這樣做。

+1

垃圾收集器是什麼? VB 6使用引用計數... – 2008-09-11 14:42:27

+0

我知道。我的意思是「將未使用的實例解除分配的東西」它是一個獨立的進程,可以處理像老化等奇特的東西。 它仍然在清理內存。真的很糟糕:) – 2008-09-11 16:12:04

+0

@AllainLalonde:「嚴格地說,」它不是垃圾收集器,在VB6中沒有其他單獨的過程。 – GiddyUpHorsey 2012-01-11 22:09:32

2

將VB6引用設置爲Nothing可減少VB對該對象的反射次數。當且僅當計數爲零時,該物體纔會被銷燬。

不要以爲只是因爲你設置爲Nothing它會像在.NET

VB6使用引用計數「垃圾收集」。

建議您設置「Nothing」instanciated對象,以引用C/C++代碼和類似的東西。自從我觸摸VB6已經很長時間了,但我記得將文件和資源設置爲無。

在任何情況下它都不會傷害(如果它已經沒有),但這並不意味着該對象將被銷燬。

VB6有一個「With/End With」語句,類似於C#.NET中的Using()語句。當然,你擁有的全球化程度越低,對你越好。

請記住,在任何一種情況下,有時創建一個大對象比保持一個引用活躍並重新使用它更昂貴。

2

我有一個類似於這個問題,然後回來。我似乎認爲這也會阻止應用程序關閉,但這可能適用於此。

我拉起舊代碼,它看起來是這樣的:

Dim y As Long 
For y = 0 To Forms.Count -1 
    Unload Forms(x) 
Next 

它可能會更安全卸載m_frm1。而不是隻將它設置爲無。

4

@馬丁

VB6有一個 「隨着/尾隨着」 語句的工作 「喜歡」 在C#.NET中使用()語句。當然,你擁有的全球化程度越低,對你越好。

隨着/尾隨着不工作,如使用的語句,它並沒有「廢棄」的語句的結束。

With/End在VB 6中工作就像它在VB.Net中一樣,它基本上是一種快速調用對象屬性/方法的方法。例如

隨着aCustomer .FirstName =「約翰」 .LastName =「史密斯」 結束與

7

其實,VB6實現RAII就像C++這意味着本地聲明引用在自動的到底得的設置爲Nothing塊。同樣,應該在執行Class_Terminate後自動重置成員類變量。但是,有幾份報告認爲這不可靠。我不記得任何嚴格的測試,但一直以來最好的做法是手動重置成員變量。

4

在VB對象具有引用計數。這意味着一個對象會保存一個有多少其他對象變量持有對它的引用的計數。當沒有對象的引用時,該對象被垃圾收集(最終)。這個過程是COM規範的一部分。

通常,當本地實例化對象超出範圍(即退出子範圍)時,其引用計數減1,換句話說引用該對象的變量被銷燬。因此在大多數情況下,您不需要在退出Sub時將對象顯式設置爲Nothing。

在所有其他情況下,您必須明確將對象變量設置爲Nothing,以便減少其引用計數(加1)。將對象變量設置爲Nothing,不一定會銷燬該對象,您必須將所有引用設置爲Nothing。對於遞歸數據結構,這個問題可能變得尤其嚴重。

另一個問題是在對象變量聲明中使用New關鍵字。一個對象只在第一次使用時創建,而不是在使用New關鍵字的時候創建。在聲明中使用New關鍵字將在每次引用計數爲零時首次使用該對象。因此,將對象設置爲Nothing可能會將其銷燬,但如果再次引用該對象,將自動重新創建該對象。理想情況下,你不應該聲明使用New關鍵字,而應該使用沒有這種復活行爲的New運算符。

2

這裏還沒有提到的一個重點是,如果沒有其他對象的引用,將對象引用設置爲Nothing將導致對象的析構函數運行(Class_Terminate,如果類是用VB編寫的)引用計數爲零)。

在某些情況下,特別是在使用RAII模式時,終止代碼可以執行可能引發錯誤的代碼。我相信一些ADODB類就是這種情況。另一個例子是封裝文件I/O的類--Class_Terminate中的代碼可能會嘗試刷新並關閉該文件,如果該文件仍處於打開狀態,則會引發錯誤。

因此,重要的是要注意,將對象引用設置爲Nothing會引發錯誤並相應地處理它(具體取決於您的應用程序 - 例如,您可以通過將「On Error Resume Next 「就在」Set ... = Nothing「之前)。

相關問題