wxWidgets / wxWidgets

Cross-Platform C++ GUI Library
https://www.wxwidgets.org/
5.75k stars 1.69k forks source link

wxListCtrl drag item crash #20066

Closed wxtrac closed 2 years ago

wxtrac commented 21 years ago

Issue migrated from trac ticket # 701

component: wxMSW | priority: normal

2002-12-30 10:36:03: anonymous created the issue


Platform: Win 98SE Python: 2.2 wxPython: 2.3.3.1

Create a wxListCtrl (with some data in it). Or run the wxPython demo.

Run your code and begin to drag* a row with mouse. (Program will'be crash!) I've tested it with and without wxLC_VIRTUAL, wxSINGLE_SEL.

On wxGTK it doesn't crash.

It seems that this is somewhat in Win98. (Perhaps a predefined drag event handling in ListCtrl-s?)

-drag: click and hold down the left button, then move your mouse.

Attila Szuts

wxtrac commented 21 years ago

2002-12-31 17:04:03: eugsadhu commented


Actually, the problem ONLY occurs if you start dragging over the text elements. If, on the other hand, you drag from the whitespace, the control registers it as a selection event.

wxtrac commented 21 years ago

2002-12-31 17:25:20: eugsadhu commented


It also crashes under wxPythonWIN32-2.3.4.2. The error box reads, "Python has caused an error in WXMSW234H.DLL." This problem also occurs under WinME.

wxtrac commented 21 years ago

2002-12-31 22:05:58: @RobinD42 commented


It doesn't happen on Win2k...

wxtrac commented 21 years ago

2002-12-31 22:08:22: eugsadhu commented


Strange. I think it may have something to do with comctl32.dll

wxtrac commented 21 years ago

2002-12-31 22:12:59: @RobinD42 commented


What version of comctl32.dll do you have? Mine is

File Version: 5.81.4916.400

wxtrac commented 21 years ago

2002-12-31 22:13:05: eugsadhu commented


When I run a debug, I get some message about an unhandled exception. I have run Spy++ to watch the Messages while trying to re-create the crash. The demo does NOT crash while Spy++ is running. I don't know if this has to do with Spy++ catching that exception. Is this possible? My comctl32 version is 5.81.

wxtrac commented 21 years ago

2002-12-31 22:27:15: eugsadhu commented


OK. I am totally confused now. If just load up the app I can make it crash. If I load up the app and then load Spy++, even without making it monitor anything, I can't get it to crash! Argh. I am at wit's end.

wxtrac commented 21 years ago

2003-01-02 17:50:07: eugsadhu commented


Even more fascinating developments . . . I installed the UNICODE wxPython (wxPythonWIN32-2.3.4.2u-Py22.exe) and discovered that the program crashes whether or not Spy++ is running.

wxtrac commented 21 years ago

2003-01-02 20:10:05: @vadz commented


I can't reproduce this under W2K in the listctrl sample. Can anyone see this in it under W98? Note that the problem might have been fixed since 2.3.3 (there were changes to the processing of some listctrl messages which resulted in a crash under XP), so please check 2.3.4 or 2.4.0.

wxtrac commented 21 years ago

2003-01-02 21:22:24: @RobinD42 commented


Vadim, I just tried it and can reproduce this on win98 with the listctrl sample. I don't have any devel tools on that box though so I can't track it down any further just yet.

wxtrac commented 21 years ago

2003-01-09 15:47:21: @vslavik commented


No luck reproducing it here (win98 cz, not SE) :(

wxtrac commented 21 years ago

2003-01-12 01:59:01: eugsadhu commented


Problem persists with WXMSW240H.DLL.

wxtrac commented 21 years ago

2003-01-13 09:53:22: attb2 commented


Perharps it could help: I've tested it in Win95(HUN version) IE5.5 and does not crash. Python: 2.2 wxPython: 2.3.3.1

wxtrac commented 21 years ago

2003-01-23 21:27:58: anonymous commented


Logged In: NO

Hello. I noticed this problem occurring in the fine wxPerl 0.12 wrapper on Windows 98 SE several days ago and submitted a bug report to that project ( http://sourceforge.net/tracker/index.php? func=detail&aid=667032&group_id=15655&atid=115655 ).

I found that on my system the wxPerl crash was exacerbated when running the PGPtray utility that comes with PGP Freeware 6.5.8 (See
http://web.mit.edu/network/pgp.html ). (PGPtray is a little system tray tool which allows you to encrypt/decrypt text in child windows of other applications. Thus it gets hooked into a lot of stuff, including the wxWindows sample LISTTEST.EXE.) By shutting down PGPtray, the ListCtrl crashes became less frequent on my system.

I built wxWindows 2.4.0 on my Cygwin 1.3.10 (gcc 2.95) environment, to check that it wasn't specifically a wxPerl problem. Sure enough (as you know) it wasn't: The wxWindows listtest.cpp sample crashed Cygwin too!

So I can confirm to you nice folks that the problem is definitely in the wxWindows library, and not with wxPerl or wxPython-specific code. There is no problem under wxGTK -- also checked.

However, the problem DOES appear to be lurking on Windows 2000, although it doesn't actually cause a crash (See below).

As some have noted here, this crash is tricky to debug. I agree: I built the wxWindows debug library ("FINAL=0") under cygwin to try to figure out what is going on. Surprisingly, I found there was NO crash anymore when linking against it instead of the optimized ("FINAL=1") version! Furthermore, this behavior appeared to be independent of whether PGPtray was running. Well, this was all bizarre and interesting, but if the crash isn't reproduced then it's not so great for debugging. :-(

Now to the useful information...

Poking around a little more showed that the code below is responsible for the crash. This comes from the file ./wxWindows-2.4.0/src/msw/listctrl.cpp :

1643:bool wxListCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)

... 1774: // set the data event field for all messages for which the system gives 1775: // us a valid NM_LISTVIEW::lParam 1776: switch ( nmLV->hdr.code ) 1777: { 1778: case LVN_BEGINDRAG: 1779: case LVN_BEGINRDRAG: 1780: case LVN_COLUMNCLICK: 1781: case LVN_ITEMCHANGED: 1782: case LVN_ITEMCHANGING: 1783: if ( iItem != -1 ) 1784: { 1785: wxListItemInternalData internaldata = 1786: (wxListItemInternalData ) nmLV-

lParam; 1787: 1788: if ( internaldata ) 1789: event.m_item.m_data = internaldata- lParam; // <--- Crash! 1790: } 1791: 1792: default: 1793: // fall through 1794: ; 1795: } ...

The right-hand-side of line 1789 is where the crash is occurring, and the reason why is that the internal data pointer obtained from nmLV->lParam is garbage. This pointer is ought to point to a wxListItemInternalData object, where the "real" lParam pointer to the user's data is kept along with wx attributes of the list item.

Whenever the nmLV->hdr.code is LVN_BEGINDRAG or LVN_BEGINRDRAG, the nmLV->lParam is apparently never filled in to the nmLV structure when the WM_NOTIFY message is generated. (Perhaps the LVIF_PARAM flag is not being set or was cleared?? But someone with more familiarity with the code than I should probably look into it.)

Anyway, on my Win98 system the nmLV->lParam pointer would typically contain a very small value, which leads to a segmentation fault when attempting to access the user's data via the wxListItemInternalData structure.

So we can see the reason for all the bizarre behavior -- why the crash depends on whether a debugger or a hook library happens to be loaded, what options are used for compilation, the COMCTRL32.DLL version, and even which mouse button (right or left) is used to start the drag: these conditions affect where the nmLV structure ends up in memory, and thus whether the residual garbage at nmLV-

lParam happens to look like a pointer to a protected area or not.

Even though the nmLV->lParam isn't valid for LVN_BEGINDRAG or LVN_BEGINRDRAG, if the value in memory at the location of nmLV->lParam just HAPPENS to look like a pointer to an accessible area in memory, then there won't be a invalid page fault. But problems will nevertheless arise, of course, when you try to do something with event.m_item.m_data. THIS APPEARS TO BE THE CASE ON WINDOWS 2000.

You may verify all this by adding an wxASSERT_MSG() like so:

1783: if ( iItem != -1 ) 1784: { 1785: wxListItemInternalData internaldata = 1786: (wxListItemInternalData ) nmLV-

lParam; 1787: 1788: if ( internaldata ) {

sprintf(myBuf, "\n\n" " nmLV: %08X\n nmLV->hdr.code: %08X\n" " nmLV->uNewState: %08X\n nmLV->uOldState: % 08X\n nmLV->uChanged: %08X\n" " LVIF_PARAM: %08X\n" " nmLV->iItem: %08X\n" " nmLV->ptAction.x: %08X\n nmLV->ptAction.y: % 08X\n" " nmLV->lParam: %08X\n", nmLV, nmLV->hdr.code, nmLV->uNewState, nmLV->uOldState, nmLV->uChanged, LVIF_PARAM, nmLV->iItem, nmLV->ptAction.x, nmLV->ptAction.y, nmLV->lParam);

wxASSERT_MSG( 0, _T(myBuf) );

1789: event.m_item.m_data = internaldata-

lParam; } 1790: }

If you do this, take note of the values of nmLV->lParam as each of the 30 items of the listtest.cpp sample are inserted into the ListCtrl and then see how different they are once you try to (right-)drag an item.

Finally, I am a total newbie with respect to wxWindows, so I want to apologize if any of the above sounds naive or incorrect; I hope it is helpful anyway. I also want to thank you for this great cross-platform framework!

-PW

wxtrac commented 21 years ago

2003-01-29 20:51:11: @RobinD42 commented


Thanks for all the info. This makes it clear that this is the same or similar problem to what we've been struggking with in another thread.

I think that this and the other bug makes it clear that we can't depend on the MSDN being very truthful when it comes to this control and the varioius versions of the comctl32.dll and so we should be very careful in our use of it...

Vadim, what do you think about removing the code mentioned by the last poster that gets the internal data from nmLV->lParam and instead using wxGetInternalData where needed in the individual message cases?

wxtrac commented 21 years ago

2003-01-30 03:38:36: @RobinD42 commented


I verified the bogus in lParam in several situations. It was always the same value (for any one run of the app) so it appears to be just an uninitialized value from comctl32. I made the change to explicitly get the data value from the control instead of relying on this value.

Change made in both branches. Please test and reopen this if there are still problems.