[Mono-list] Problem with Dispose() and unmanaged resources

Matthijs ter Woord (meddochat) meddochat@zonnet.nl
Tue, 4 Jan 2005 19:12:45 +0100


Hi Edd,

Please check out the GC.SuppressFinalize function.

Matthijs ter Woord



----- Original Message ----- 
From: "Edd Dumbill" <edd@usefulinc.com>
To: <mono-list@lists.ximian.com>
Sent: Tuesday, January 04, 2005 5:42 PM
Subject: [Mono-list] Problem with Dispose() and unmanaged resources


> Hi,
> 
> In Redland# we use the pattern described by Microsoft for using
> IDisposable to wrap unmanaged resources, described here:
> http://makeashorterlink.com/?Y3861282A
> 
> I have a private member of type IntPtr set to the unmanaged resource,
> and a P/Invoke to a cleanup C function is made in the Dispose call, and
> then the member set to IntPtr.Zero, as described under "Implementing a
> Dispose method".
> 
> The problem is that -- when Dispose is run from the Finalizer (that is,
> Dispose wasn't called before the object was GC'd) -- it seems the IntPtr
> member has already been finalized, and there's a NullReferenceException
> generated.  Under Mono 1.0.4 this prints out:
> 
> Unhandled Exception: System.NullReferenceException: Object reference not
> set to an instance of an object
> 
> And then the runtime hangs.  This happens only occasionally, and less
> frequently if I'm generating trace output.
> 
> Many of the traced sessions look a bit like this:
> 
> ENTER: (wrapper runtime-invoke) System.Object:runtime_invoke_void
> (object,intptr,intptr,intptr)([Redland.Serializer:0x8096a90], (nil),
> 0xb6a659c8, 0xb619e2a0, ). ENTER: Redland.Serializer:Finalize
> ()(this:0x8096a90[Redland.Serializer test.exe], )
> . . ENTER: Redland.Serializer:Dispose
> (bool)(this:0x8096a90[Redland.Serializer test.exe], 0, )
> . . . ENTER: (wrapper managed-to-native)
> Redland.Serializer:librdf_free_serializer (intptr)(0x8172ba8, )
> . . . . ENTER: (wrapper runtime-invoke)
> System.Object:runtime_invoke_void
> (object,intptr,intptr,intptr)([System.NullReferenceException:0x8098c90],
> (nil), (nil), 0xb619e3b0, )
> . . . . . ENTER: System.NullReferenceException:.ctor
> ()(this:0x8098c90[System.NullReferenceException test.exe], )
> . . . . . . ENTER: Locale:GetText (string)([STRING:0x8111c78:A null
> value was found where an object instance was required.], )
> . . . . . . LEAVE: Locale:GetText (string)[STRING:0x8111c78:A null value
> was found where an object instance was required.]
> . . . . . LEAVE: System.NullReferenceException:.ctor ()
> . . . . LEAVE: (wrapper runtime-invoke)
> System.Object:runtime_invoke_void
> (object,intptr,intptr,intptr)[OBJECT:(nil)]
> EXCEPTION handling: NullReferenceException
> EXCEPTION: finally clause 0 of Redland.Serializer:Finalize ()
> . . . . ENTER: System.Object:Finalize
> ()(this:0x8096a90[Redland.Serializer test.exe], )
> . . . . LEAVE: System.Object:Finalize ()
> EXCEPTION: catch found at clause 0 of (wrapper runtime-invoke)
> System.Object:runtime_invoke_void (object,intptr,intptr,intptr)
> 
> What I see happening above is the NullReferenceException being thrown
> when it attempts to pass the value of the private IntPtr to the C
> cleanup function, librdf_free_serializer().
> 
> I pulled Mono SVN HEAD to see if things worked any different there.  The
> good news is that we no longer seem to get the random hangs that 1.0.4
> generates, but the trace shows that the NullReferenceException thing is
> still happening.  At the best, this means memory leaks are going to
> happen.
> 
> Have I got something wrong here, or is there a bug with finalizing
> classes?  The code is structured just the way the MSDN example suggests.
> 
> -- Edd
> 
> 
> _______________________________________________
> Mono-list maillist  -  Mono-list@lists.ximian.com
> http://lists.ximian.com/mailman/listinfo/mono-list
>