Microsoft KB Archive/309327

= PRB: Premature Garbage Collection of Object Reference =

Article ID: 309327

Article Last Modified on 11/29/2007

-

APPLIES TO


 * Microsoft Common Language Runtime (included with the .NET Framework) 1.0

-



This article was previously published under Q309327



Caution ADO and ADO MD have not been fully tested in a Microsoft .NET Framework environment. They may cause intermittent issues, especially in service-based applications or in multithreaded applications. The techniques that are discussed in this article should only be used as a temporary measure during migration to ADO.NET. You should only use these techniques after you have conducted complete testing to make sure that there are no compatibility issues. Any issues that are caused by using ADO or ADO MD in this manner are unsupported. For more information, see the following article in the Microsoft Knowledge Base:

840667 You receive unexpected errors when using ADO and ADO MD in a .NET Framework application



SYMPTOMS
If a managed object contains a reference to an unmanaged resource, and the object has a finalizer method to release the unmanaged resource, make sure that the object is alive until all platform invoke (PInvoke) calls that use the unmanaged resource have completed. Otherwise, Garbage Collection may collect the object, which causes the object's finalizer to release the unmanaged resource. Any later references to that resource may result in an Access Violation or memory corruption.



RESOLUTION
The resolution to this problem depends on the nature of the unmanaged resource. For the purpose of this article, unmanaged resources fall into two catagories:
 * Resources that are handles to operating system objects.
 * Resources that are not handles to operating system objects.

When you use Interop Services, there are two mechanisms for interoperating with unmanaged code. One is the Platform Invoke Service, which allows managed code to call unmanaged functions that are implemented in dynamic-link libraries (DLLs). The other mechanism is COM Interop, which is a bi-directional service that bridges between the .NET Framework and COM components.

PInvoke and Handles to Operating System Objects
When you work with handles to operating system objects, such as window handles and device contexts, use the HandleRef structure to wrap the resources. Platform Interop Services works with the HandleRef structure.

Note In the following COM Interop example, this problem is resolved by making calls to the KeepAlive method of the Garbage Collector. Although this will work with Platform Invoke calls, HandleRef is the recommended approach. Option Strict On Option Explicit On

Imports System.Runtime.InteropServices

Module Module1

Private Declare Function GetGraphicsMode Lib &quot;gdi32&quot; Alias &quot;GetGraphicsMode&quot; _ (ByVal hdc As HandleRef) As Integer Private Declare Function GetDC Lib &quot;user32&quot; _ (ByVal hwnd As IntPtr) As IntPtr Private Declare Function ReleaseDC Lib &quot;user32&quot; _ (ByVal hwnd As IntPtr, ByVal hdc As HandleRef) As Integer

Class Test Public hdcscreen As HandleRef

Public Sub New hdcscreen = New HandleRef(Me, GetDC(IntPtr.Zero)) End Sub

Protected Overrides Sub Finalize Dim ret As Integer ret = ReleaseDC(IntPtr.Zero, hdcscreen) MyBase.Finalize End Sub End Class

Sub Main Dim mvb As New Test Dim GrMode As Integer GrMode = GetGraphicsMode(mvb.hdcscreen) Console.Write(GrMode.ToString) End Sub

End Module

COM Interop and Other Types of Resources
For resources where HandleRef is not applicable, such as a database connection, use GC.KeepAlive to maintain an object's existence, as in the following sample code: Imports System Imports System.Reflection

Module MyModule Sub Main

Dim conn = Activator.CreateInstance(Type.GetTypeFromProgId(&quot;ADODB.Connection&quot;)) conn.Open _ (&quot;Provider=SQLOLEDB.1;Data Source=(local);Integrated Security=SSPI;Initial Catalog=pubs&quot;) Dim rs = conn.Execute(&quot;SELECT * FROM employee&quot;)

Dim id If Not rs.EOF Then id = rs(&quot;emp_id&quot;).Value Console.WriteLine(id) Else Console.WriteLine(&quot;Empty Recordset&quot;) End If

GC.KeepAlive(conn) GC.KeepAlive(rs) GC.KeepAlive(id)

End Sub End Module 

For more about automatic memory management, visit the following Microsoft Developer Network Web site:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/csspec/html/vclrfCSharpSpec_3_9.asp

Additional query words: kbreadme

Keywords: kbnofix kbprb kbreadme kbupgrade KB309327

-

[mailto:TECHNET@MICROSOFT.COM Send feedback to Microsoft]

© Microsoft Corporation. All rights reserved.