[Mono-list] issue with pinvoke memory leak
hi, i have the following sitution (not directly mono related but maybe interesting regardless since a lot of pinvoke is going on here) that I do not know how to handle cleanly: i have been playing with a wrapper for an image library with the following method: private static extern FIBITMAP FreeImage_Rescale(FIBITMAP dib, int dst_width, int dst_height, FilterOption filter); I had implemented it like this: public FreeImage Resample(int newwidth, int newheight, FilterOption filter) which works fine with something like: FreeImage img2 = img.Resample(100,100,FilterOption.BILINEAR); but when I do: img = img.Resample(100,100,FilterOption.BILINEAR); then the img object is 'replaced' but a I have a big memory leak, since the Dispose() method which handles the cleanup of unmanaged resources (the img object has a pointer to the unmanaged image data which is normally released when the object is disposed) is never called. Can someone give me a tip how to handle this in a way that ensures that the old data from img is disposed in the second case above? Actaully, would this same issue be a problem for all IDisposable objects in managed code (maybe I am not allowed to do this at all with IDisposable objects) or is this unique to the managed/unmanaged code in question here? Thanks for any feedback! Regards, --chris ___ Mono-list maillist - [EMAIL PROTECTED] http://lists.ximian.com/mailman/listinfo/mono-list
Re: [Mono-list] issue with pinvoke memory leak
Hi Ravindra, again, thanks for the tip. I checked and the finalizer was there only it was not getting called (or not often enough) - i added a GC.Collect() call to my test class and it worked. Thanks again! Regards, --chris On Wed, 2 Jun 2004, Ravindra wrote: Hello, On Wed, 2004-06-02 at 17:00, Chris Turchin wrote: i have been playing with a wrapper for an image library with the following method: private static extern FIBITMAP FreeImage_Rescale(FIBITMAP dib, int dst_width, int dst_height, FilterOption filter); I had implemented it like this: public FreeImage Resample(int newwidth, int newheight, FilterOption filter) which works fine with something like: FreeImage img2 = img.Resample(100,100,FilterOption.BILINEAR); but when I do: img = img.Resample(100,100,FilterOption.BILINEAR); then the img object is 'replaced' but a I have a big memory leak, since the Dispose() method which handles the cleanup of unmanaged resources (the img object has a pointer to the unmanaged image data which is normally released when the object is disposed) is never called. Can someone give me a tip how to handle this in a way that ensures that the old data from img is disposed in the second case above? Actaully, would this same issue be a problem for all IDisposable objects in managed code (maybe I am not allowed to do this at all with IDisposable objects) or is this unique to the managed/unmanaged code in question here? Dude, you need to implement finalizer for your FreeImage class. Finalizer method would do all the required cleanup you want to do. GC would call your class finalizer, when you are done with the referenced object. - Ravindra ___ Mono-list maillist - [EMAIL PROTECTED] http://lists.ximian.com/mailman/listinfo/mono-list
Re: [Mono-list] issue with pinvoke memory leak
On Wed, 2004-06-02 at 08:09, Chris Turchin wrote: Hi Ravindra, again, thanks for the tip. I checked and the finalizer was there only it was not getting called (or not often enough) - i added a GC.Collect() call to my test class and it worked. Don't call GC.Collect(). Please. Under .NET, manually calling GC.Collect will throw off the algorithms that govern when .NET normally collects memory, which can negatively impact performance. Though relying on the finalizer will already impact performance, as finalizers aren't run until after the object graph has been promoted a generation. For example, if it's a Generation 0 object that has a finalizer and is collected, it's promoted to Generation 1 and the finalizer isn't run until the *next* Generation 1 collection. Which is less frequent than Generation 0 collections. If your object is promoted to Generation 2, it'll hang around awhile. Result: you may have lots of unmanaged memory leaking, because it's waiting for the collector to finalize the object... (Imagine that you have a 10 MB image opened in unmanaged memory and held open by a managed handle. It may be awhile before that memory is freed.) Assuming, of course, that the finalizer is *ever* executed, and there is no guarantee that it will be. In short, finalizers are nice as a fall back, but DO NOT rely on them. You have to remember to dispose of your resources in a timely basis. Consequently, you should instead do: FreeImage img = GetImage (); FreeImage img2 = img.Resample (...); img.Dispose (); img = img2; That's assuming that you really need to do the aliasing. If you don't need to keep re-using the img variable, you could use the using block: using (FreeImage img = GetMyImage()) { using (FreeImage img2 = img.Resample (...)) { // operate on img2 } } This will ensure that your unmanaged memory is freed in a timely manner. Mono doesn't currently use a generational collector, so this currently isn't as much of an issue. snip/ Actaully, would this same issue be a problem for all IDisposable objects in managed code (maybe I am not allowed to do this at all with IDisposable objects) or is this unique to the managed/unmanaged code in question here? This is true for all IDisposable objects. If the object doesn't have a finalizer, then nothing will be invoked when the object is collected. Either invoke Dispose() directly, or use a using block so that Dispose() is called for you. This should be done for all resources -- unmanaged memory, database locks, file handles, monitors... Everything that may be limited and needs to be released in a timely manner to avoid performance issues. Finalizers can help in freeing these resources, but they're no guarantee. Use them as a fall-back ONLY. - Jon ___ Mono-list maillist - [EMAIL PROTECTED] http://lists.ximian.com/mailman/listinfo/mono-list