This project is read-only.

GDIPLUSx garbage collection

Topics: General, Attention VFPX Admins
Mar 28, 2007 at 4:53 PM
I'm working on some code to do image resizing and thumbnail creation based on Cesar's example. I'm achieving the desired results in terms of creation of resized and thumbnail images. However, when the system object goes out of scope, it throws an exception (StatusInvalidParameter). My guess here is the handle created for the resized bitmap has been released prior to the point when the system object is being destroyed and this in turn results in a bad value being passed. In the development environment, an assertion fires when the exception occurs and I can ignore the error to move on but it leaves this orphaned unknown datasession. Since asserts don't fire in an exe, I don't think this will impact there unless there are unreleased resources that might accumulate from multiple invocations of the form methods I'm using. Having said that, is there some kind of cleanup method that needs to be explicitly invoked in order to properly release any objects created from these classes? In the several examples I've looked at here, none of them appear to do any explicit cleanup of the GDI+ objects created.

TIA,

Richard Kaye
Mar 29, 2007 at 1:58 AM
Edited Mar 29, 2007 at 2:03 AM
Hi Richard,

Each wrapper class that creates an GDI+ object is deleting the object in the Destroy event. So it should be taken care of automatically.

That being said. There may be a timing issue that is possibly compounded by objects being created in the scope of a non-default DataSession. There will be a problem if the System object goes out of scope before all GDI+ objects are destroyed. This is one of the reasons we recommend adding the System object to the _SCREEN object, and then forget about it. Any GDI+ objects you create "should" go out of scope before the _SCREEN drops the System object.

If the System object was instatiated while inside of a non-default DataSession, the System object will belong to that DataSession. When the DataSession tries to go out of scope it may delete (or try to delete) the System object before all of the GDI+ objects are destoyed.

I think your solution would be to move the instatiation of the System object to the beginning of your application (with the default DataSession selected). Then any GDI+ object you create will belong to the default DataSession and should clean up in order.

It is also a good idea to clean up any GDI+ objects when you are done with them. Either set the reference to NULL or call the Dispose method.

I hope this helps,
Bo Durban

Mar 29, 2007 at 2:31 PM
Hi Bo,

Thanks for the rapid response and also your contributions to the Sedna/VFPX world.

My original plan was to only create these objects as needed and not at app startup. Having said that, I will try your suggestion.

In my testing, I have tried explicitly nulling the objects in the reverse order created. For example, there are 4 objects being created, similar to Cesar's example; a system object and then 3 bitmap type objects - loImage, loResized & loGfx. The 3 bitmap objects go away without complaint. It's only the final system object that caused me a problem. And this happens regardless of adding the system object to _screen or just using a local var reference. I was setting them NULL as opposed to calling the Dispose method. I'll try that, too.

BTW, I have been using Cesar's original gpimage prg to perform this same function and the new classes are significantly faster and much less memory intensive.
Mar 30, 2007 at 2:23 PM
Just to clarify, the problem is the System object throwing the exception. Adding the object to _screen at app startup displays the same behavior when the System object goes out of scope at app exit.

The form's orphaned datasession closes properly if I switch to the default datasession before adding the System object and then switch back to the form's datasession.

I took a quick tour through that class and it does not appear to have a Dispose method. I'm wondering if it is being caused by the creation of child objects such as Drawing. In either case, it definitely has no discernable impact in an EXE.

Thanks again for your comments.
Apr 2, 2007 at 6:33 PM
Is the ASSERT coming from your own error trapping or from the GDIPlusX library? Is there an error message and line number you can point me to in the library that the error occurs? How is the System object going out of scope?

Thanks
Apr 4, 2007 at 12:28 PM
Richard,
We're very interested in this error.
The library throws an exception object when an internal error occurs.
Can you "Suspend" the execution when the error occurs ? Then expand the object "loException" in the treeview from the debugger, and please tell us exactly in what line the error occurs, and in whick method, etc...
Thanks,
Cesar
Apr 4, 2007 at 1:56 PM
The assert is happening in the GDI+X library. I've been heads down on a server migration and will get back to you as soon as I can with more specific info.
Apr 5, 2007 at 10:45 PM
Thanks Richard,
So we'll be looking forward to your feedback about this error.
Cesar