Stack overflow problem in Win95
jeffg@iqpuucp.aa.iqsc.com Tuesday, February 06, 1996 Okay, this one has been bothering me for a while and I have absolutely no idea what to do about it. Our main development platform is WinNt 3.51. The product was originally 16-bit and recently ported to 32-bit (our 32-bit release is creeping up on me slowly). The program works just as expected under WinNT, however, when I run it under Win95, I get errors that don't seem to be related to our source, but to window DLLs, etc. Here is some briefing material: Output window: First-chance exception in Iqobject.exe: 0xC00000FD: Stack Overflow. Stack: AfxAssertFailedLine(char * 0x00697f60, int 217) line 39 + 19 bytes AfxUnlockGlobals(int 6) line 217 + 35 bytes CWnd::OnWndMsg(unsigned int 31, unsigned int 0, long 0, long * 0x00892a58) line 1665 CWnd::WindowProc(unsigned int 31, unsigned int 0, long 0) line 1617 + 30 bytes AfxCallWndProc(CWnd * 0x0098f888 {CIQPropertySheet hWnd=0x000005a8}, HWND__ * 0x000005a8, unsigned int 31, unsigned int 0, long 0) line 209 + 26 bytes AfxWndProc(HWND__ * 0x000005a8, unsigned int 31, unsigned int 0, long 0) line 362 + 25 bytes KERNEL32! bff73663() KERNEL32! bff928e0() 00007b6e() Some source for AfxUnlockGlobals in afxcrit.cpp: // allow exclusive access if thread is waiting for it if (_afxGlobalThreadId != GetCurrentThreadId()) { EnterCriticalSection(&_afxTempLock); if (--_afxNonExclusiveCount == 0) VERIFY(SetEvent(_afxExclusiveLock)); ASSERT(_afxNonExclusiveCount >= 0); LeaveCriticalSection(&_afxTempLock); } The problem is on the "VERIFY(SetEvent" line. I should mention that the program runs as expected in release mode (although I don't know how much confidence I should take in "as expected"). This only occurs in debug mode. It's a pain during development to keep getting this stack overflow problem. Btw, I am using a 1MB stack (default for MSDEV 4.0). Any input would be appreciated.
djw@arbortext.com Thursday, February 08, 1996 Our product is written without MFC; it's just a C program using the Win32 api. When we first ran it on Windows 95, we were getting a seg fault when certain dialog boxes were popped up. It turned out that Win95 made some low-level change in the relationship between the three components of a combobox. We were hanging user data off one of the component windows of the combobox, but later trying to retrieve the data in a different context. On NT, and using Win32s, we were "seeing" the same component in the latter context, that we had hung the data off of. On Win95, we were looking at a different component. (Sorry for not remembering more precisely which component was involved in each case.) This is yet another case where the MFC style of doing things (i.e. using class member variables to carry user information along with a window) would have avoided the problem entirely. At any rate, I believe we simply ran into a case where Microsoft made a change that wasn't expected to hurt anyone. The new arrangement might very well be more logical, or more efficient, for some reason. We might also have been doing something that wasn't the recommended practice, so I intend no criticism of Microsoft at all. My point is simply that Windows 95 doesn't do everything exactly the same as NT did, and it's possible to trip on one of the differences. On the other hand, once we solved that single problem, our very large application ran successfully on Win95. We had to fix some minor color problems in dynamically created dialog boxes, but I'm certain, in those cases, that our problems were entirely caused by us doing some slightly unconventional things in painting controls. The wider borders Win95 uses in some controls made a little tweaking of the sizes of dropdown lists, etc., necessary to fit in the same content as on NT. While we aren't yet taking advantage of new Win95 interface features, I was astonished at how little work was required to be able to release a version that runs ok on the new operating system. Dave djw@arbortext.com
Mike Blaszczak -- mikeblas@msn.com Friday, February 09, 1996 [Mini-digest: 3 responses] > First-chance exception in Iqobject.exe: 0xC00000FD: Stack Overflow. It turns out that a stack overflow exception can be thrown if you smash the stack pointer or stack frame and the machine can notice that. This isn't the same kind of "Stack Overflow" most people think of--the kind where you push too much stuff on the stack or get into a huge infinite recursion problem. Your stack trace is this: AfxAssertFailedLine(char * 0x00697f60, int 217) line 39 + 19 bytes AfxUnlockGlobals(int 6) line 217 + 35 bytes CWnd::OnWndMsg(unsigned int 31, unsigned int 0, long 0, long * 0x00892a58) line 1665 (thanks for providing it, BTW) It means that you've called AfxUnlockGlobals from CWnd::OnWndMsg(). If you look at WINCORE.CPP, you'll see that AfxUnlockGlobals is called during the handling of the message. Unforuntately, I can't tell _exactly_ what the problem is because I have a different version than MFC 4.0 on my machine and the lines don't match up. The message being sent around is WM_CANCELMODE (because the first parameter to OnWndMsg() is 0x1F), which implies that your handling of this message (or a related override called before the message is actually dispatched) is screwing up the stack and causing the crash. So, I would start with figuring out what's going on with regard to that message in your app. It's likely you're tromping the stack. .B ekiM -----From: Geoffrey Nicholls>My point is simply that Windows 95 doesn't do everything exactly the >same as NT did, and it's possible to trip on one of the differences. True. I found another. I tried to subclass CFileDialog to change the the text on the "Open" button. In 3.1 and NT you can handle the OnInitDialog message and get the child window whose id is IDOK and call SetWindowText(). In Win95, a new subclass mechanism that doesn't require a system specific dialog layout in your rc file, makes the "Open" button a child of the parent window whose id is IDOK. Pretty easy once you know. Easy to trip on. Geoff Nicholls -----From: mikeblas@interserv.com On Thu, 08 Feb 96, djw@arbortext.com wrote: >At any rate, I believe we simply ran into a case where Microsoft made a >change that wasn't expected to hurt anyone. This relationship isn't documented. At best I think it's discussed in a couple of KB articles. Generally, things like are good to stay away from. If you decide you need them, you should comment them heavily so you're (and others) are reminded to test them when you change platforms and reinvestigate them when you change the code surrounding them. This is why I don't like guys like Andrew Schulman. By exposing the innards of the way Windows work, people end up reading his books and then implementing applications which are [heavily] dependent on that implementation. When Microsoft starts upgrading Windows, it has to try using tons of commercial applications to see if they've pulled stunts like this. If they have, then the program managers and product managers have to have a big meeting with a couple developers to see if a workaround to the sloppy code in the application is feasible. You'd never _believe_ how much code is in Windows just to deal with applications which use some of the undocumented things floating around in Windows. There are pages of comments like this in the Windows source: // we have to make sure the pointer to the thingamajig in this // wahoo structure is NULL until _all_ applications have whappenjabbered. // this is mainly to ensure compatibility with Some Popular Program, and // Some Other Popular Program which assume that the undocumented dodad // will _not_ reinitialize the pointer to the thingamajig. And each of those comments if followed by boatloads of special-case code to work around things which are technically bugs in the other applications. Some of the compatibility hacks in Windows 3.1 are documented in the Windows 3.1 Resource Kit, where the SYSTEM.INI "CompatibilityFlag" parameter is documented. Then again, maybe it's a _good_ idea to use undocumented features haphazardly; that can get your application some free publicity. .B ekiM -- TCHAR szDisc[] = _T("These words are my own; I do not speak for Microsoft.");
| Вернуться в корень Архива |