Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / .NET Framework / CLR / September 2003

Tip: Looking for answers? Try searching our database.

Premature collection of objects with live references in Framework v1.1.4322

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Laurent Thérond - 19 Sep 2003 23:49 GMT
Hi,

I have a C library making callbacks to methods of CLR-
based objects.

Because (maybe) these CLR-based callbacks never appear to
be invoked from the CLR standpoint, the garbage collector
assumes it is fine to collect their arguments.

In other words, objects with live references are being
collected, even though they are being accessed later on
in those callbacks.

This appears as a very serious defect.

Has anyone else experienced this?

Does Microsoft intend to correct this problem?

Regards,

Laurent
Jay B. Harlow [MVP - Outlook] - 20 Sep 2003 02:44 GMT
Laurent,
You need to let the GC know there is an outstanding reference to the object.

> I have a C library making callbacks to methods of CLR-
> based objects.
I'm not following you here. Are you saying you have a C library that is
hosting the CLR and you are calling into the CLR

Or you have a managed program and you are calling a C library, that is then
calling back to the CLR?

I have not tried this, but from Managed code you can use
System.GC.KeepAlive. to ensure a reference to the object for the lifetime of
a method.

There is also System.Runtime.InteropServices.GCHandle &
System.Runtime.InteropServices.HandleRef which may be more appropriate to
what you are attempting.

Hope this helps
Jay

> Hi,
>
[quoted text clipped - 18 lines]
>
> Laurent
Laurent Thérond - 20 Sep 2003 03:33 GMT
Jay,

First, another description of the situation:

A .NET library wraps a C resource provided by the C side
with a C# object and passes this C# object to a C# user
callback. The wrapping C# object is a parameter to the C#
user callback. Even though the C# user callback accesses
the wrapping object, the wrapping object is collected, its
finalizer is called and the C resource is
released...leading to a crash when the C# user callback
finally attempts to access the C resource via the
wrapping object.

The delegates are fine. They do not disappear. I take
care of that.

The C library passes an IntPtr to my delegate. I pass
this IntPtr to the constructor of a C# class. I pass the
resulting object as a parameter to the C# user callback.
Before the C# user callback gets a chance to access the
resource pointed to by the IntPtr contained in the
wrapping object, the wrapping object is collected. Hence
the finalizer for the object is called and the native
resource is released. (since I have code to release the
native resource in the finalizer of the wrapping object)

Regards,

Laurent

>-----Original Message-----
>Laurent,
[quoted text clipped - 20 lines]
>
>"Laurent Thérond" <ltherond@Concentual.com> wrote in
message
>news:8dff01c37f00$538d42c0$a601280a@phx.gbl...
>> Hi,
[quoted text clipped - 21 lines]
>
>.
Jay B. Harlow [MVP - Outlook] - 20 Sep 2003 14:52 GMT
Laurent,
I give up, :-| I'm not even going to try to visualize what you are
attempting (sounds like spaghetti ;-) in a good way)

Does one of the following solve your problem?
   System.GC.KeepAlive
   System.Runtime.InteropServices.GCHandle
   System.Runtime.InteropServices.HandleRef

From what I do follow of your description, I believe you need to use one of
the later two (read I would expect one of the later to solve your problem).
Adam Nathan's book ".NET and COM - The Complete Interoperability Guide" has
descriptions of how to use the above.

Hope this helps
Jay

Jay,

First, another description of the situation:

A .NET library wraps a C resource provided by the C side
with a C# object and passes this C# object to a C# user
callback. The wrapping C# object is a parameter to the C#
user callback. Even though the C# user callback accesses
the wrapping object, the wrapping object is collected, its
finalizer is called and the C resource is
released...leading to a crash when the C# user callback
finally attempts to access the C resource via the
wrapping object.

The delegates are fine. They do not disappear. I take
care of that.

The C library passes an IntPtr to my delegate. I pass
this IntPtr to the constructor of a C# class. I pass the
resulting object as a parameter to the C# user callback.
Before the C# user callback gets a chance to access the
resource pointed to by the IntPtr contained in the
wrapping object, the wrapping object is collected. Hence
the finalizer for the object is called and the native
resource is released. (since I have code to release the
native resource in the finalizer of the wrapping object)

Regards,

Laurent

>-----Original Message-----
>Laurent,
>You need to let the GC know there is an outstanding
reference to the object.

>> I have a C library making callbacks to methods of CLR-
>> based objects.
>I'm not following you here. Are you saying you have a C
library that is
>hosting the CLR and you are calling into the CLR
>
>Or you have a managed program and you are calling a C
library, that is then
>calling back to the CLR?
>
>I have not tried this, but from Managed code you can use
>System.GC.KeepAlive. to ensure a reference to the object
for the lifetime of
>a method.
>
>There is also System.Runtime.InteropServices.GCHandle &
>System.Runtime.InteropServices.HandleRef which may be
more appropriate to
>what you are attempting.
>
>Hope this helps
>Jay
>
>"Laurent Th?rond" <ltherond@Concentual.com> wrote in
message
>news:8dff01c37f00$538d42c0$a601280a@phx.gbl...
>> Hi,
[quoted text clipped - 3 lines]
>>
>> Because (maybe) these CLR-based callbacks never appear
to
>> be invoked from the CLR standpoint, the garbage
collector
>> assumes it is fine to collect their arguments.
>>
[quoted text clipped - 13 lines]
>
>.
Laurent Thérond - 20 Sep 2003 16:39 GMT
Thanks, Jay.

I use GCHandle in some parts of the code to create
autoreferences and prevent certain critical objects from
being collected.

Using GC.KeepAlive can fix the problem I describe, but,
frankly, a) the GC should never garbage objects with live
references, b) if you have to tell the GC how and when to
collect things, it's no longer automatic memory
management and you might as well revert to explicit
memory management.

L.

>-----Original Message-----
>Laurent,
[quoted text clipped - 15 lines]
>
>"Laurent Thérond" <ltherond@Concentual.com> wrote in
message
>news:0a9701c37f1f$8b45b160$a301280a@phx.gbl...
>Jay,
[quoted text clipped - 87 lines]
>
>.
Jay B. Harlow [MVP - Outlook] - 20 Sep 2003 18:25 GMT
Laurent,
If you stay within managed code it is automatic memory management!

You are mixing managed (C#) & unmanaged (C) code, the automatic memory
management is not able to deal with the unmanaged memory. How is it going to
know what is going on in the unmanaged code? (unless you tell it) I hope you
realized its called unmanaged for a reason.

Hence the need for those three classes to help the managed memory manager
out, when handing managed objects off to unmanaged code.

For details on how the Managed Memory Manager works see:

http://msdn.microsoft.com/msdnmag/issues/1100/gci/
http://msdn.microsoft.com/msdnmag/issues/1200/GCI2/

Just a thought
Jay

Thanks, Jay.

I use GCHandle in some parts of the code to create
autoreferences and prevent certain critical objects from
being collected.

Using GC.KeepAlive can fix the problem I describe, but,
frankly, a) the GC should never garbage objects with live
references, b) if you have to tell the GC how and when to
collect things, it's no longer automatic memory
management and you might as well revert to explicit
memory management.

L.

>-----Original Message-----
>Laurent,
>I give up, :-| I'm not even going to try to visualize
what you are
>attempting (sounds like spaghetti ;-) in a good way)
>
[quoted text clipped - 4 lines]
>
>From what I do follow of your description, I believe you
need to use one of
>the later two (read I would expect one of the later to
solve your problem).
>Adam Nathan's book ".NET and COM - The Complete
Interoperability Guide" has
>descriptions of how to use the above.
>
>Hope this helps
>Jay
>
>"Laurent Th?rond" <ltherond@Concentual.com> wrote in
message
>news:0a9701c37f1f$8b45b160$a301280a@phx.gbl...
>Jay,
[quoted text clipped - 6 lines]
>user callback. Even though the C# user callback accesses
>the wrapping object, the wrapping object is collected,
its
>finalizer is called and the C resource is
>released...leading to a crash when the C# user callback
[quoted text clipped - 62 lines]
>>> In other words, objects with live references are being
>>> collected, even though they are being accessed later
on
>>> in those callbacks.
>>>
[quoted text clipped - 11 lines]
>
>.
Laurent Thérond - 21 Sep 2003 02:43 GMT
I realize I must have not conveyed what happens correctly.

The CLR garbage collector collects a managed wrapper
objects even though this managed wrapper object still has
live references.

You told me I should use GC.KeepAlive to prevent this
managed wrapper object from being collected and I tell
you I should not need to give such clues to the GC when
there are live references to that wrapper object.

I agree with everything else you said.

Regards,

Laurent

>-----Original Message-----
>Laurent,
[quoted text clipped - 17 lines]
>
>"Laurent Thérond" <ltherond@Concentual.com> wrote in
message
>news:00d401c37f8d$61c78d90$a101280a@phx.gbl...
>Thanks, Jay.
[quoted text clipped - 131 lines]
>
>.
Jay B. Harlow [MVP - Outlook] - 21 Sep 2003 03:48 GMT
Laurent,
> I realize I must have not conveyed what happens correctly.
>
> The CLR garbage collector collects a managed wrapper
> objects even though this managed wrapper object still has
> live references.
I understood you created this managed wrapper, then handed it completely off
to unmanaged code (via a delegate/callback?). By completely I mean there is
no longer an actual reference to it from a managed object that you have a
reference to. A circular reference (only) between objects where one gets
handed off to unmanaged code, do not count, as you just surrendered your
managed reference to the objects.

Reading an earlier post, maybe I have the above backwards.

Do you actually maintain a reference to the managed wrapper from managed
code?

Can you post code samples? Enough to get a good feel for what you are
actually doing as I am not following the descriptions (remember a picture
(code) is worth a thousand words).

Thanks
Jay

I realize I must have not conveyed what happens correctly.

The CLR garbage collector collects a managed wrapper
objects even though this managed wrapper object still has
live references.

You told me I should use GC.KeepAlive to prevent this
managed wrapper object from being collected and I tell
you I should not need to give such clues to the GC when
there are live references to that wrapper object.

I agree with everything else you said.

Regards,

Laurent

>-----Original Message-----
>Laurent,
>If you stay within managed code it is automatic memory
management!

>You are mixing managed (C#) & unmanaged (C) code, the
automatic memory
>management is not able to deal with the unmanaged
memory. How is it going to
>know what is going on in the unmanaged code? (unless you
tell it) I hope you
>realized its called unmanaged for a reason.
>
>Hence the need for those three classes to help the
managed memory manager
>out, when handing managed objects off to unmanaged code.
>
[quoted text clipped - 7 lines]
>
>"Laurent Th?rond" <ltherond@Concentual.com> wrote in
message
>news:00d401c37f8d$61c78d90$a101280a@phx.gbl...
>Thanks, Jay.
[quoted text clipped - 44 lines]
>>with a C# object and passes this C# object to a C# user
>>callback. The wrapping C# object is a parameter to the
C#
>>user callback. Even though the C# user callback accesses
>>the wrapping object, the wrapping object is collected,
[quoted text clipped - 27 lines]
>>>
>>>> I have a C library making callbacks to methods of
CLR-
>>>> based objects.
>>>I'm not following you here. Are you saying you have a C
[quoted text clipped - 6 lines]
>>>
>>>I have not tried this, but from Managed code you can
use
>>>System.GC.KeepAlive. to ensure a reference to the
object
>>for the lifetime of
>>>a method.
[quoted text clipped - 13 lines]
>>>>
>>>> I have a C library making callbacks to methods of
CLR-
>>>> based objects.
>>>>
>>>> Because (maybe) these CLR-based callbacks never
appear
>>to
>>>> be invoked from the CLR standpoint, the garbage
>>collector
>>>> assumes it is fine to collect their arguments.
>>>>
>>>> In other words, objects with live references are
being
>>>> collected, even though they are being accessed later
>on
[quoted text clipped - 15 lines]
>
>.

Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.