TQtCustomControl.viewportDelete deletes FViewPortWidget when insided eventhandle for FViewPortWidget
Original Reporter info from Mantis: djenkins @dfjenkins
-
Reporter name: David Jenkins
Original Reporter info from Mantis: djenkins @dfjenkins
- Reporter name: David Jenkins
Description:
We use a toolbar button to move an output window in and out of the main window. The original mouse event goes through TQWidget.eventFilter with self = TQtViewPort. The mouse action ends up calling a reparent that destroys TQtcustomcontrol and TQtviewport. This means that TQtcustomControl.viewportDelete is called and FreeAndNil is called on FViewPortWidget. The object that FViewPortWidget points is the same TQtViewPort whose eventfilter we are sitting in. The TQtViewpoRt is deleted and then later .endeventprocessing is entered and with the correct corruption of memory .Free is called on the already deleted object.
Steps to reproduce:
I am attaching a an example project that shows everything except the crash that we see. With a breakpoint in TQtCustomControl.viewportDelete you can see that the object being deleted is the same object whose eventhandler routine we are in.
The crash is not seen because the free'd memory doesn't sit around long enough to have values changed inside of it. So when EndEventProcessing is called the values for FInEventCount and FReleaseInEvent are not such that .Free is called. In fact in the example project w/o heaprtc turned on , the memory manager has already returned the same pointer to a new instance of TQtViewPort and the it has been re-initialized. I turned on heaptrc with keepreleased enabled so this wouldn't happen. So you can seen that the self object inside of TQtObject.EndEventProcessing has already been .free'd but it won't crash because FInEventCount and FReleaseInEvent are not corrent for calling .Free.
In our code, a lot of creating and releaseing occurs such that occasionally the memory associated with FinventCount = 0 and FReelaseInvent = true. When that happens a crash will occur.
Additional information:
Suggested fix is to replace call to FreeAndNil(FViewPortWidget) in TQtCustomControl.viewportDelete with
FViewPortWidget.FOwner := nil;
FViewPortWidget.Release ;
FViewPortWidget := nil;
Diff file attached.
Mantis conversion info:
- Mantis ID: 28264
- Version: 1.4
- Fixed in revision: 49299 (#edabee3d)