Tracing a windows run time error

This question at end of this message...

The previous question:

I wrote a C++ program in using Visual Studio that usually runs fine. I have given a "win32 release"
build copy to my users.

It occasionally crashes and give the users an "Illeagal Operations" message box.

Ho do I use the data from this message box to figure out where in my program the crashing is initiated
(using the debugger of course) - so I can try and fix it!


The previously accepted answer (from jhance):

The stack traceback is quite useful.  Be sure you have the EXACT build that caused the crash and be
sure you have the MAP and COD files being generated by your release build.  These are not on by default.

1) Starting at the EIP, find that address RANGE in your MAP file.  It will say what obj file had that
address.  If it's one of your files, then continue.  Othwise go to the stack traceback and work from
the top of the list down until you find an address RANGE that relates to some code you wrote.

2) Now, calculate the OFFSET from the address in the crash report from the beginning of the obj module.
Also note the NAME of the function in the MAP file.  It will be a decorated name.

3) Now open the COD file for the obj you've located.  Find the function by name that you located in
the MAP file.  Then move forward the number of bytes you calculated in the offset.

4) You've arrived at the SOURCE CODE LINE that caused the fault.  Usually the problem is obvious.

Here is the question:

I have all the MAP and COD files and the details of the error message - but I cant seem to find from all this the like of my code that caused the problem. I would like to send someone the three files and see if they can make something of it.
Who is Participating?
I think the problem you had was that you took a function from a library (i.e. CArray::GetAt) that was called from more than one place.  From there, you don't know how the app reached that point.  So the key thing in examining the stack when the fault happens in a library module is to work backwards (from the top down) until you reach the first function return address that references a function in your application.  In this case it is your function "OnNewMessage" that CALLS CArray::GetAt.  So now you know where the fault happend (CARray::GetAt) and where it was called from (OnNewMessage in OPTION.CPP line 354).

Now the only question that remains is WHY the crash.  Use your debugger or some ASSERT/VERIFY statments to track it down...

>>I would like to send someone the three files and
>>see if they can make something of it.
Can you post a link the your files instead?
Could you just post the stack trace?
Cloud Class® Course: Ruby Fundamentals

This course will introduce you to Ruby, as well as teach you about classes, methods, variables, data structures, loops, enumerable methods, and finishing touches.

AustinKalbAuthor Commented:
we dont have a website or ftp site accessable to the public. do you know somewhere?
I have a PAQ on EE somewhere that gave a step-by-step explanation of how to do this but I'll be darned if I can figure out the EE Search Engine....Arghhhh....

Please have a look at:
AustinKalbAuthor Commented:
i went through it over and over.. i still cant seem to get back to one on my source lines!
I don't really like to repeat myself, but:

Could you just post the stack trace?

How will AustinKalb's stack trace help you to debug?  Unless I'm missing something, you cannot do anything with it without the source code, MAP file, and COD files.


Did you follow my instructions on the web page?  Where did it breakdown?  Please explain.....
AustinKalbAuthor Commented:
sorry jkr - I missed that last time!

MULTIQUOTE caused an invalid page fault in
module MFC42.DLL at 017f:5f403
EAX=ffffffff CS=017f EIP=5f403eba EFLGS=00010202
EBX=7800c283 SS=0187 ESP=006692d4 EBP=00669304
ECX=0066954c DS=0187 ESI=0066954c FS=181f
EDX=00000440 ES=0187 EDI=0079b120 GS=0000
Bytes at CS:EIP
83 78 f4 00 of 8c 8e 7c 05 00 89 06 83 c0 f4 50
Stack Dump:
006694fc 0079b120 00420136 0079b120 00000004
0066ae08 00660c8f 00000000 00669554 00428148
00000000 0040cad0 00669554 0041e23f 006694fc

Here's what I found:
from the map file -
 0001:0001f080       ?GetAt@?$CArray@UOPTIONQUOTE@@U1@@@QBE?AUOPTIONQUOTE@@H@Z 00420080 f i Option.obj

and from the cod file -
_nIndex$ = 12
___$ReturnUdt$ = 8
$T86554 = -16
__$EHRec$ = -12

; 254  :       { ASSERT(nIndex >= 0 && nIndex < m_nSize);

  00000      55             push       ebp
  00001      8b ec             mov       ebp, esp
  00003      83 e4 f8       and       esp, -8                  ; fffffff8H
  00006      6a ff             push       -1
  00008      68 00 00 00 00       push       $L86576
  0000d      64 a1 00 00 00
      00             mov       eax, DWORD PTR fs:__except_list
  00013      50             push       eax
  00014      64 89 25 00 00
      00 00             mov       DWORD PTR fs:__except_list, esp
  0001b      83 ec 08       sub       esp, 8

; 255  :             return m_pData[nIndex]; }

  0001e      8b 45 0c       mov       eax, DWORD PTR _nIndex$[ebp]
  00021      8b 49 04       mov       ecx, DWORD PTR [ecx+4]
  00024      56             push       esi
  00025      57             push       edi
  00026      8b 7d 08       mov       edi, DWORD PTR ___$ReturnUdt$[ebp]
  00029      8d 14 80       lea       edx, DWORD PTR [eax+eax*4]
  0002c      c7 44 24 0c 00
      00 00 00       mov       DWORD PTR $T86554[esp+28], 0
  00034      8d 04 50       lea       eax, DWORD PTR [eax+edx*2]
  00037      8d 34 c1       lea       esi, DWORD PTR [ecx+eax*8]
  0003a      8b cf             mov       ecx, edi
  0003c      56             push       esi
  0003d      e8 00 00 00 00       call       ??0CString@@QAE@ABV0@@Z      ; CString::CString
  00042      8b 56 08       mov       edx, DWORD PTR [esi+8]
  00045      83 c6 50       add       esi, 80                  ; 00000050H
  00048      89 57 08       mov       DWORD PTR [edi+8], edx
  0004b      8b 46 bc       mov       eax, DWORD PTR [esi-68]
  0004e      89 47 0c       mov       DWORD PTR [edi+12], eax
  00051      8b 4e c0       mov       ecx, DWORD PTR [esi-64]
  00054      89 4f 10       mov       DWORD PTR [edi+16], ecx
  00057      8b 56 c8       mov       edx, DWORD PTR [esi-56]
  0005a      89 57 18       mov       DWORD PTR [edi+24], edx
  0005d      8b 46 cc       mov       eax, DWORD PTR [esi-52]
  00060      89 47 1c       mov       DWORD PTR [edi+28], eax
  00063      8b 4e d0       mov       ecx, DWORD PTR [esi-48]
  00066      89 4f 20       mov       DWORD PTR [edi+32], ecx
  00069      8b 56 d4       mov       edx, DWORD PTR [esi-44]
  0006c      89 57 24       mov       DWORD PTR [edi+36], edx
  0006f      8b 46 d8       mov       eax, DWORD PTR [esi-40]
  00072      89 47 28       mov       DWORD PTR [edi+40], eax
  00075      8b 4e dc       mov       ecx, DWORD PTR [esi-36]
  00078      89 4f 2c       mov       DWORD PTR [edi+44], ecx
  0007b      8b 56 e0       mov       edx, DWORD PTR [esi-32]
  0007e      89 57 30       mov       DWORD PTR [edi+48], edx
  00081      8b 46 e4       mov       eax, DWORD PTR [esi-28]
  00084      89 47 34       mov       DWORD PTR [edi+52], eax
  00087      8b 4e e8       mov       ecx, DWORD PTR [esi-24]
  0008a      89 4f 38       mov       DWORD PTR [edi+56], ecx
  0008d      8b 56 f0       mov       edx, DWORD PTR [esi-16]
  00090      89 57 40       mov       DWORD PTR [edi+64], edx
  00093      8b 46 f4       mov       eax, DWORD PTR [esi-12]
  00096      89 47 44       mov       DWORD PTR [edi+68], eax
  00099      8b 4e f8       mov       ecx, DWORD PTR [esi-8]
  0009c      89 4f 48       mov       DWORD PTR [edi+72], ecx
  0009f      8b 56 fc       mov       edx, DWORD PTR [esi-4]
  000a2      56             push       esi
  000a3      8d 4f 50       lea       ecx, DWORD PTR [edi+80]
  000a6      c7 44 24 1c 00
      00 00 00       mov       DWORD PTR __$EHRec$[esp+40], 0
  000ae      89 57 4c       mov       DWORD PTR [edi+76], edx
  000b1      e8 00 00 00 00       call       ??0CString@@QAE@ABV0@@Z      ; CString::CString
  000b6      8b 4c 24 10       mov       ecx, DWORD PTR __$EHRec$[esp+28]
  000ba      8b c7             mov       eax, edi
  000bc      5f             pop       edi
  000bd      64 89 0d 00 00
      00 00             mov       DWORD PTR fs:__except_list, ecx
  000c4      5e             pop       esi
  000c5      8b e5             mov       esp, ebp
  000c7      5d             pop       ebp
  000c8      c2 08 00       ret       8

the line:
; 255  :             return m_pData[nIndex]; }
 is not mine!

>>0001:0001f080       ?GetAt@?$CArray@UOPTIONQUOTE@@U1@@@QBE?AUOPTIONQUOTE@@H@Z 00420080 f i Option.obj

Why did you pick this function?  I don't see it.  I'd suggest you look for the following addresses from the stack:


Starting at the top of the list.  The EIP is obviously bogus since it's outside the bounds of any program execution address.
AustinKalbAuthor Commented:
I picked that function because the next function's address was greater than 0020136:

 0001:0001ef80       ?GetQuoteTime@COption@@QAE?AVCTime@@H@Z 0041ff80 f   Option.obj
 0001:0001f080       ?GetAt@?$CArray@UOPTIONQUOTE@@U1@@@QBE?AUOPTIONQUOTE@@H@Z 00420080 f i Option.obj
 0001:0001f150       ?SetAt@?$CArray@UOPTIONQUOTE@@U1@@@QAEXHUOPTIONQUOTE@@@Z 00420150 f i Option.obj
AustinKalbAuthor Commented:
.. oops..

greater than 00420136
And, btw, you posted the stack dump, not the trace - couldn't you have your app crash with DrWatson being activated? :o)
AustinKalbAuthor Commented:
we're running win 98. how do I get Dr.Watson to run. Havent seen that in some time!
jkrCommented: ('Description of the Dr. Watson (Drwatson.exe) Tool') - this article claims to apply for Win98/ME ;-)
OK,I understand now...

So the problem is at:
000b1     e8 00 00 00 00      call      ??0CString@@QAE@ABV0@@Z     ; CString::CString
 000b6     8b 4c 24 10      mov      ecx, DWORD PTR __$EHRec$[esp+28]

My guess here is that you are dealing with a NULL comparison with a CString or something similar.  
When you say:

the line:
; 255  :           return m_pData[nIndex]; }
is not mine!

what do you mean??  This is line 255 from the file Option.cpp.  Are you saying that there is NOT such a line in your file?

AustinKalbAuthor Commented:
I am. there is no such line in that file. when i search for that snipit of code, i get results in

C:\Program Files\Microsoft Visual Studio\VC98\MFC\INCLUDE\AFXCOLL.INL(25):          return m_pData[nIndex]; }


C:\Program Files\Microsoft Visual Studio\VC98\MFC\INCLUDE\AFXTEMPL.H(263):          return m_pData[nIndex]; }

looks like a problem with collection classes, but where is my offensive line of code!
AustinKalbAuthor Commented:
The MAP files, COD files, and a bitmap of the error box can be gotten at ftp site / anonymous login. They're zipped into I can put other files there as well. Let me know what yuou need.

AustinKalbAuthor Commented:
I put a Dr Watson file on the FTP site. Can someone help me interpet the error. My program is "Multiquote.exe"

What FTP site?
AustinKalbAuthor Commented:
from above message:

ftp site / anonymous login
OK, here is my analysis:

First, the error:


is in MFC42.DLL and so the actual abend is not in your code.  But your code call this and so we need to work backwards...

The next thing on the stack is:

>>0187:00669564 017f:0041e23f MULTIQUOTE.EXE:.text+0x1d23f

Which is found here:

 0001:0001cbe0       ?OnNewMessage@COption@@QAEXVCString@@@Z 0041dbe0 f   Option.obj
 0001:0001e250       ?UpdateStdDisplay@COption@@AAEXXZ 0041f250 f   Option.obj

The address 41e23f is in the function ?OnNewMessage@COption@@QAEXVCString@@@Z

at offset 41e23f - 41dbe0 = 0x65F

Which is generated by line:

; 354  :           m_regional = optionQuote.GetAt(nRegionalPosition);

My guess?  You have a problem with the data in "nRegionalPosition" and it is causing a fault in CString.  NULL maybe?  Note that eax in your register trace = 0x00000000.  This is NULL.
Oops.. Everything is OK but the last statement.  I thought that optionQuote was a CString but I see that it is a CArray instead.  Now my guess is that the value, nRegionalPosition is out of bounds for the CArray...

Note that the EXACT place where the fault is happening is the line:

  0065a     e8 00 00 00 00      call      ?GetAt@?$CArray@UOPTIONQUOTE@@U1@@@QBE?AUOPTIONQUOTE@@H@Z ; CArray<OPTIONQUOTE,OPTIONQUOTE>::GetAt

which is the call to GetAt.  Something is wrong with either the CArray object or the value you are passing to it.  Debug!!
I guess I also have another question.  What pervented you from doing exactly what I did above yourself?  I followed the procedure that I referred you to before.  

I'd like to improve the description of the procedure and would appreciate any feedback.
AustinKalbAuthor Commented:
if you check the map and option.cod file (ziped in the ftp site) I actually traced to line 7598 of the cod file - which somehow didnt get me back to line 354 of option.cpp. Maybe you can help me - what did I miss?
1) The ERROR is in the function:

0001:0001cbe0       ?OnNewMessage@COption@@QAEXVCString@@@Z 0041dbe0 f   Option.obj

2) The ADDRESS of this function is 0041dbe0.

3) The ADDRESS of the place where the stack points us is:
0187:00669564 017f:0041e23f MULTIQUOTE.EXE:.text+0x1d23f
or 0041e23f

4) 41e23f - 41dbe0 = 0x65F

5) Search the OPTION.COD file for the function:
That gets to line:

?OnNewMessage@COption@@QAEXVCString@@@Z PROC NEAR     ; COption::OnNewMessage, COMDAT

Note the PROC NEAR that marks this as the START of the function.  Then we need to go 0x65F BYTES (not lines) forward to:

  0065f     89 44 24 18      mov      DWORD PTR $T85795[esp+588], eax

(This is line 3529 in your OPTION.COD file).

This is where the STACK is pointing when the fault happens.  Well the STATEMENT BEFORE this is the problem since it's a function call and a function call pushes the address of the NEXT INSTRUCTION after itself for the RET to return to...

So the culprit is line 3528 of your OPTION.COD file:

  0065a     e8 00 00 00 00      call      ?GetAt@?$CArray@UOPTIONQUOTE@@U1@@@QBE?AUOPTIONQUOTE@@H@Z ; CArray<OPTIONQUOTE,OPTIONQUOTE>::GetAt
>>I actually traced to line 7598 of the

What I can't figure out is how you got to line 7598.  I don't see the connection.
Well, OK.  Perhaps there is a connection.  The code at line 7598 is quite similar:

; 977  :      m_regional = optionQuote.GetAt(regionalPosition);

etc... and to..

  00032     e8 00 00 00 00      call      ?GetAt@?$CArray@UOPTIONQUOTE@@U1@@@QBE?AUOPTIONQUOTE@@H@Z ; CArray<OPTIONQUOTE,OPTIONQUOTE>::GetAt

Perhaps the SAME problem manifesting itself in different places at different time.  But the SPECIFIC crash you captured in the DR WATSON log is the original one I posted, not this one...
AustinKalbAuthor Commented:
ok - so here's where I got lost. When I first used the map file I looked for the address before 00420136:

0001:0001f080       ?GetAt@?$CArray@UOPTIONQUOTE@@U1@@@QBE?AUOPTIONQUOTE@@H@Z 00420080 f i Option.obj

Which led to:


in the cod file (line 7959).

So the problem was how I used the stack to find the function that gave me the error. Maybe one should transverse the stack dump from the bottom up looking for an address on the 04 range?
AustinKalbAuthor Commented:
I understand.. thanks for your help!
Glad you got it.  May I ask what the final result was?
AustinKalbAuthor Commented:
I cant seem to make the program fail.. the users sure can. I put some statements in the release version that will notify the users of certian potential problem situations before the GetAt statement. Hopefully, I can track down the WHY that way.
>>I cant seem to make the program fail.. the users sure can

Darned users!  Don't you wish there was some way of getting rid of users.  Hmmm, that solves one problem but opens up another.  

Did you ever get to the bottom of this?
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.