15 мая 2023 года "Исходники.РУ" отмечают своё 23-летие!
Поздравляем всех причастных и неравнодушных с этим событием!
И огромное спасибо всем, кто был и остаётся с нами все эти годы!

Главная Форум Журнал Wiki DRKB Discuz!ML Помощь проекту


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.");





| Вернуться в корень Архива |