For the TURBU engine, I’ve got a custom control that allows me to embed an OpenGL rendering context on a form. I was working on some new features, and I downloaded gDEBugger, an OpenGL debugging tool, to help out. One of the things it told me is that my rendering contexts were leaking.
They shouldn’t be. I create the renderer in CreateWnd and I destroy it in DestroyWnd, which should get called as part of the component destruction process. But as it turns out, DestroyWnd is not actually called anywhere!
By tracing through the VCL code, it looks like DestroyWnd is supposed to get called from a call stack that looks something like this:
But earlier in the form destruction process, TWinControl.Remove gets called. It does not call RemoveControl on the control being removed, and at the end of the routine, it says:
AControl.FParent := nil;
By directly setting the field to nil instead of calling SetParent(nil), it makes it so that when SetParent(nil) is called, the entire body of code gets short-circuited, so that RemoveControl is never called. In fact, it’s not just my control. I put a breakpoint on the first line of TWinControl.DestroyHandle, ran the program, and closed it, which generates and then frees almost 30 TWinControl descendants. The breakpoint was never hit.
I’m seeing this in Delphi XE. I haven’t tested it in any other version, but from what I can see, it appears that any VCL control created in XE will never call DestroyHandle during component destruction, leading to all window handles (and other resources, such as my rendering contexts) being leaked.
Can anyone confirm this, or say if it affects other versions? I didn’t see this in QC, so I wrote up a bug report. Please vote for it, especially if you work on a program with lots of complex forms and have users who would be, shall we say, unamused to suddenly hit an “out of resources” error for no good reason…