Unhandled exceptions in comctl32.dll and ntdll.tll

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
Skah T
In need of some credit
In need of some credit
Posts: 5
Joined: Mon Apr 03, 2006 10:30 pm

Unhandled exceptions in comctl32.dll and ntdll.tll

Post by Skah T »

I'm getting an unhandled exception in my project. I haven't tracked down any specific code change that might have caused this. After debugging a while it seems to be a problem in either the windows DLL (perish the thought) or wxWidgets event handling. In fact I was having the exact same problem as this post, but it has now changed to be an exception in comctl32.dll rather than ntdll.dll.

It happens when I double-click an entry in my wxTreeCtrl. Strangely if I single click the item and press ENTER, which should have the same effect as a double-click, the exception does not occur.

Any help is much appreciated. Stepping through comctl32.dll assembler code is not my idea of a fun afternoon.

Here's the full register and stack dump. The exception happens when comctl32 tries to dereference the address 0xBAADF00D. I don't know where this bogus data is originating, but a quick search of the WX source doesn't find that value, so I'm not sure who to suspect.

Code: Select all

EAX = 00159248 EBX = 00159248 ECX = 00019BB7 EDX = 0000F00D 
ESI = BAADF00D EDI = 00000000 EIP = 5D0A78D8 ESP = 0012F050 
EBP = 0012F058 EFL = 00000282 

comctl32.dll!_TV_CountVisibleDescendants@4()  + 0x13	
comctl32.dll!_TV_ScrollBelow@16()  + 0x43	
comctl32.dll!_TV_Expand@16()  + 0xf2	
comctl32.dll!_TV_ButtonDown@24()  + 0x10c	
comctl32.dll!_TV_WndProc@16()  + 0x336d	
user32.dll!_InternalCallWinProc@20()  + 0x28	
user32.dll!_UserCallWinProcCheckWow@32()  + 0xb7	
user32.dll!_CallWindowProcAorW@24()  + 0x51	
user32.dll!_CallWindowProcA@20()  + 0x1b	
NVShmoo.exe!wxWindow::MSWDefWindowProc(unsigned int nMsg=0x00000203, unsigned int wParam=0x00000001, long lParam=0x00750058)  Line 1956 + 0x27	C++
NVShmoo.exe!wxTreeCtrl::MSWDefWindowProc(unsigned int nMsg=0x00000203, unsigned int wParam=0x00000001, long lParam=0x00750058)  Line 2662	C++
NVShmoo.exe!wxWindow::MSWWindowProc(unsigned int message=0x00000203, unsigned int wParam=0x00000001, long lParam=0x00750058)  Line 3021 + 0x1c	C++
NVShmoo.exe!wxTreeCtrl::MSWWindowProc(unsigned int nMsg=0x00000203, unsigned int wParam=0x00000001, long lParam=0x00750058)  Line 2619 + 0x14	C++
NVShmoo.exe!wxWndProc(HWND__ * hWnd=0x00480654, unsigned int message=0x00000203, unsigned int wParam=0x00000001, long lParam=0x00750058)  Line 2326 + 0x1c	C++
user32.dll!_InternalCallWinProc@20()  + 0x28	
user32.dll!_UserCallWinProcCheckWow@32()  + 0xb7	
user32.dll!_DispatchMessageWorker@8()  + 0xdc	
user32.dll!_DispatchMessageW@4()  + 0xf	
user32.dll!_IsDialogMessageW@8()  + 0xdb	
user32.dll!_IsDialogMessageA@8()  + 0x4a	
NVShmoo.exe!wxWindow::MSWProcessMessage(tagMSG * pMsg=0x0012fc24)  Line 2200 + 0x1d	C++
NVShmoo.exe!wxEventLoop::PreProcessMessage(tagMSG * msg=0x0012fc24)  Line 211 + 0x14	C++
NVShmoo.exe!wxEventLoop::ProcessMessage(tagMSG * msg=0x0012fc24)  Line 107 + 0x11	C++
NVShmoo.exe!wxEventLoop::Dispatch()  Line 420 + 0x11	C++
NVShmoo.exe!wxEventLoop::Run()  Line 282 + 0xd	C++
NVShmoo.exe!wxAppBase::MainLoop()  Line 272 + 0x15	C++
NVShmoo.exe!wxAppBase::OnRun()  Line 340 + 0x10	C++
NVShmoo.exe!wxEntryReal(int & argc=0x00000002, char * * argv=0x00ffa280)  Line 439 + 0x1b	C++
NVShmoo.exe!wxEntry(int & argc=0x00000002, char * * argv=0x00ffa280)  Line 216 + 0xd	C++
NVShmoo.exe!wxEntry(HINSTANCE__ * hInstance=0x00400000, HINSTANCE__ * __formal=0x00000000, HINSTANCE__ * __formal=0x00000000, int nCmdShow=0x00000001)  Line 386 + 0xd	C++
NVShmoo.exe!WinMain(HINSTANCE__ * hInstance=0x00400000, HINSTANCE__ * hPrevInstance=0x00000000, char * lpCmdLine=0x00141f15, int nCmdShow=0x00000001)  Line 251 + 0x33	C++
NVShmoo.exe!WinMainCRTStartup()  Line 390 + 0x39	C
kernel32.dll!_BaseProcessStart@4()  + 0x23
tan
wxWorld Domination!
wxWorld Domination!
Posts: 1471
Joined: Tue Nov 14, 2006 7:58 am
Location: Saint-Petersburg, Russia

Re: Unhandled exceptions in comctl32.dll and ntdll.tll

Post by tan »

Hi,
Skah T wrote: It happens when I double-click an entry in my wxTreeCtrl. Strangely if I single click the item and press ENTER, which should have the same effect as a double-click, the exception does not occur.
Do you handle double click event yourself? Can you share some code of that?
OS: Windows XP Pro
Compiler: MSVC++ 7.1
wxWidgets: 2.8.10
Skah T
In need of some credit
In need of some credit
Posts: 5
Joined: Mon Apr 03, 2006 10:30 pm

Post by Skah T »

Indirectly. I handle EVT_TREE_ITEM_ACTIVATED, but not the double click specifically.

I also forgot to say that I'm using 2.6.3, but I also tried 2.8.2 to see if something had been fixed. Both do the same thing.

I did find out that if I comment out a single line in my event handler the exception does not occur. The line is calling wxChoice::Add() and no matter what string I pass in the exception occurs. The pointer to the wxChoice is definitely valid. Anyway, the exception does not happen at that line, or even anywhere in my event handler. It hits after my handler has returned and all the calling methods are returning.
tan
wxWorld Domination!
wxWorld Domination!
Posts: 1471
Joined: Tue Nov 14, 2006 7:58 am
Location: Saint-Petersburg, Russia

Post by tan »

Skah T wrote:Indirectly. I handle EVT_TREE_ITEM_ACTIVATED, but not the double click specifically.

I also forgot to say that I'm using 2.6.3, but I also tried 2.8.2 to see if something had been fixed. Both do the same thing.

I did find out that if I comment out a single line in my event handler the exception does not occur. The line is calling wxChoice::Add() and no matter what string I pass in the exception occurs. The pointer to the wxChoice is definitely valid. Anyway, the exception does not happen at that line, or even anywhere in my event handler. It hits after my handler has returned and all the calling methods are returning.
Hmm.. wxChoice doesn't have Add() method :) is it a typo?
Any way, without any sample code nobody can help you.
OS: Windows XP Pro
Compiler: MSVC++ 7.1
wxWidgets: 2.8.10
Skah T
In need of some credit
In need of some credit
Posts: 5
Joined: Mon Apr 03, 2006 10:30 pm

Post by Skah T »

Sorry, I meant Append() :)

I'll dig into it more myself. If I can't figure it out I'll try to create a small example and post it here.
Skah T
In need of some credit
In need of some credit
Posts: 5
Joined: Mon Apr 03, 2006 10:30 pm

Post by Skah T »

More info. Not really expecting an answer from anyone - I just want to document this in case it's useful to others.

In my EVT_TREE_ITEM_ACTIVATED event handler I am deleting part of the tree, including the item that caused the event. I'm wondering if that is the problem.

Looking at the memory dump as I step through I can see all the tree items allocated and all makes sense. Then my event hits and I see the items removed as expected - the associated memory frees and gets written with 0xFEEEFEEE.

Then my wxChoice::Append() hits and it allocates some memory for the new item - it happens to use the space that was just freed. That section of memory now becomes 0xBAADF00D (aside from the part that gets the choice item text).

Finally, the call stack starts unwinding and for some reason comctl32.dll tries to reference the tree item that was just deleted. This gets the 0xBAADF00D and causes the exception.

If I comment out the Append() call it works okay, though I would expect it to still fail since reading 0xFEEEFEEE is no better than 0xBAADF00D. I'm now investigating the difference between the passing and failing cases.
Skah T
In need of some credit
In need of some credit
Posts: 5
Joined: Mon Apr 03, 2006 10:30 pm

Post by Skah T »

Here's why the commented out Append() does not cause the exception.

The routine within comctl32.dll called "_TV_Expand@16" tests a flag in the now-deleted tree item. In the bad version this flag data is 0xBAADF00D and in the good version it is 0xFEEEFEEE. This makes the flag test pass in one case and fail in another. In the bad case _TV_Expand@16 eventually calls _TV_ScrollBelow@16, which leads to the exception within _TV_CountVisibleDescendants@4. In the good case Expand returns without calling ScrollBelow.

I'm pretty convinced that the problem is that my event handler is deleting the tree item that caused the event.

Now my question becomes, am I doing something illegal?
tan
wxWorld Domination!
wxWorld Domination!
Posts: 1471
Joined: Tue Nov 14, 2006 7:58 am
Location: Saint-Petersburg, Russia

Post by tan »

Hi,
Skah T wrote:Here's why the commented out Append() does not cause the exception.

The routine within comctl32.dll called "_TV_Expand@16" tests a flag in the now-deleted tree item. In the bad version this flag data is 0xBAADF00D and in the good version it is 0xFEEEFEEE. This makes the flag test pass in one case and fail in another. In the bad case _TV_Expand@16 eventually calls _TV_ScrollBelow@16, which leads to the exception within _TV_CountVisibleDescendants@4. In the good case Expand returns without calling ScrollBelow.

I'm pretty convinced that the problem is that my event handler is deleting the tree item that caused the event.

Now my question becomes, am I doing something illegal?
I guess you have to call Skip() at the end of your handler.
OS: Windows XP Pro
Compiler: MSVC++ 7.1
wxWidgets: 2.8.10
Post Reply