Page 1 of 1

Unhandled exceptions in comctl32.dll and ntdll.tll

Posted: Tue Mar 20, 2007 12:11 am
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 

[email protected]()  + 0x13	
[email protected]()  + 0x43	
[email protected]()  + 0xf2	
[email protected]()  + 0x10c	
[email protected]()  + 0x336d	
[email protected]()  + 0x28	
[email protected]()  + 0xb7	
[email protected]()  + 0x51	
[email protected]()  + 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++
[email protected]()  + 0x28	
[email protected]()  + 0xb7	
[email protected]()  + 0xdc	
[email protected]()  + 0xf	
[email protected]()  + 0xdb	
[email protected]()  + 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
[email protected]()  + 0x23

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

Posted: Tue Mar 20, 2007 6:35 am
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?

Posted: Tue Mar 20, 2007 1:44 pm
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.

Posted: Tue Mar 20, 2007 2:21 pm
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.

Posted: Tue Mar 20, 2007 4:35 pm
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.

Posted: Tue Mar 20, 2007 11:42 pm
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.

Posted: Wed Mar 21, 2007 12:11 am
by Skah T
Here's why the commented out Append() does not cause the exception.

The routine within comctl32.dll called "[email protected]" 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 [email protected] eventually calls [email protected], which leads to the exception within [email protected] 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?

Posted: Wed Mar 21, 2007 6:26 am
by tan
Hi,
Skah T wrote:Here's why the commented out Append() does not cause the exception.

The routine within comctl32.dll called "[email protected]" 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 [email protected] eventually calls [email protected], which leads to the exception within [email protected] 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.