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.");
| Вернуться в корень Архива
|