How to debug an "Access violation reading location 0" not from a trivial error
-
Monday, September 12, 2011 8:30 PM
I'm looking for some helpful suggestions about how to debug this problem. I get "First-chance exception at 0x01376e31 in InitUtil.exe: 0xC0000005: Access violation reading location 0x00000000." Some background on the situation: 1) The code in the immediate area of the crash does work when called in very simple context, it only fails in a more complex situation. 2) It will fail every time, in exactly the same place. 3) The additional complexity has nested dialogs, lambda code, inheritance, and some use of pointers in classes. 4) The last user interaction was to press OK on a dialog which should start a process of reading the double string from a text box, and convert it into a double member variable. One function higher in the call stack, text is "2.71": double getDouble( int id ) { std::string text= getText( id ); std::stringstream ss ( text ); double retv; ss >> retv; ===> return retv; } - this 0x01414068 {dialogHwnd=0x00260552 controls=[12]({nextId=1002 classOfItem=Static textForItem="elevation" ...},{nextId=1002 classOfItem=Edit textForItem="20" ...},{nextId=1002 classOfItem=Static textForItem="height" ...},{nextId=1002 classOfItem=Edit textForItem="20" ...},{nextId=1002 classOfItem=Static textForItem="ratio" ...},{nextId=1002 classOfItem=Edit textForItem="2.71" ...},{nextId=1002 classOfItem=Static textForItem="fireplace" ...},{nextId=1002 classOfItem=Button textForItem="" ...},{nextId=1002 classOfItem=Static textForItem="description" ...},{nextId=1002 classOfItem=Edit textForItem="Covered with ice, overlooking the bay." ...},{nextId=1002 classOfItem=Button textForItem="Cancel" ...},{nextId=1002 classOfItem=Button textForItem="OK" ...}) } ZX::Dialog * const + dialogHwnd 0x00260552 {unused=??? } HWND__ * + controls [12]({nextId=1002 classOfItem=Static textForItem="elevation" ...},{nextId=1002 classOfItem=Edit textForItem="20" ...},{nextId=1002 classOfItem=Static textForItem="height" ...},{nextId=1002 classOfItem=Edit textForItem="20" ...},{nextId=1002 classOfItem=Static textForItem="ratio" ...},{nextId=1002 classOfItem=Edit textForItem="2.71" ...},{nextId=1002 classOfItem=Static textForItem="fireplace" ...},{nextId=1002 classOfItem=Button textForItem="" ...},{nextId=1002 classOfItem=Static textForItem="description" ...},{nextId=1002 classOfItem=Edit textForItem="Covered with ice, overlooking the bay." ...},{nextId=1002 classOfItem=Button textForItem="Cancel" ...},{nextId=1002 classOfItem=Button textForItem="OK" ...}) std::vector<ZX::DialogControlBase,std::allocator<ZX::DialogControlBase> > id 1005 int - ss {_Stringbuffer={...} } std::basic_stringstream<char,std::char_traits<char>,std::allocator<char> > - std::basic_iostream<char,std::char_traits<char> > {...} std::basic_iostream<char,std::char_traits<char> > + std::basic_istream<char,std::char_traits<char> > {_Chcount=0 } std::basic_istream<char,std::char_traits<char> > + std::basic_ostream<char,std::char_traits<char> > {...} std::basic_ostream<char,std::char_traits<char> > - _Stringbuffer {_Seekhigh=0x00b94dd4 "ýýýý««««««««" _Mystate=1 _Al={...} } std::basic_stringbuf<char,std::char_traits<char>,std::allocator<char> > + std::basic_streambuf<char,std::char_traits<char> > {_Mylock={...} _Gfirst=0x00b94dd0 "2.71ýýýý««««««««" _Pfirst=0x00b94dd0 "2.71ýýýý««««««««" ...} std::basic_streambuf<char,std::char_traits<char> > + _Seekhigh 0x00b94dd4 "ýýýý««««««««" char * _Mystate 1 int + _Al {...} std::allocator<char> retv -9.2559631349317831e+061 double + text "2.71" std::basic_string<char,std::char_traits<char>,std::allocator<char> > And then the exception occurs on this code at the "====>" _Myt& __CLR_OR_THIS_CALL operator>>(double& _Val) { // extract a double 01376DC0 push ebp 01376DC1 mov ebp,esp 01376DC3 push 0FFFFFFFFh 01376DC5 push offset __ehhandler$??5?$basic_istream@DU?$char_traits@D@std@@@std@@QAEAAV01@AAN@Z (13E6923h) 01376DCA mov eax,dword ptr fs:[00000000h] 01376DD0 push eax 01376DD1 push ecx 01376DD2 sub esp,180h 01376DD8 push ebx 01376DD9 push esi 01376DDA push edi 01376DDB push ecx 01376DDC lea edi,[ebp-190h] 01376DE2 mov ecx,60h 01376DE7 mov eax,0CCCCCCCCh 01376DEC rep stos dword ptr es:[edi] 01376DEE pop ecx 01376DEF mov eax,dword ptr [___security_cookie (14124E8h)] 01376DF4 xor eax,ebp 01376DF6 push eax 01376DF7 lea eax,[ebp-0Ch] 01376DFA mov dword ptr fs:[00000000h],eax 01376E00 mov dword ptr [ebp-10h],esp 01376E03 mov dword ptr [ebp-18h],ecx ios_base::iostate _State = ios_base::goodbit; 01376E06 mov dword ptr [ebp-24h],0 const sentry _Ok(*this); 01376E0D push 0 01376E0F mov eax,dword ptr [ebp-18h] 01376E12 push eax 01376E13 lea ecx,[ebp-34h] 01376E16 call std::basic_istream<char,std::char_traits<char> >::sentry::sentry (12F7FE0h) 01376E1B mov dword ptr [ebp-4],0 if (_Ok) 01376E22 lea eax,[ebp-170h] 01376E28 push eax 01376E29 lea ecx,[ebp-34h] 01376E2C call std::basic_istream<char,std::char_traits<char> >::sentry::operator int std::_Bool_struct::* (12F84CCh) ====> 01376E31 mov ecx,dword ptr [eax] 01376E33 mov dword ptr [ebp-184h],ecx etc The registers are: EAX = 00000000 EBX = 00000001 ECX = 0037D60C EDX = 0037D60C ESI = 0037DAB8 EDI = 0037D630 EIP = 01376E31 ESP = 0037D49C EBP = 0037D640 EFL = 00010246 so it is no surprise that I get an error from reading from address 0. The debugger shows these variables: - this 0x0037d740 {_Chcount=0 } std::basic_istream<char,std::char_traits<char> > * const - std::basic_ios<char,std::char_traits<char> > {_Mystrbuf=0x0037d758 _Tiestr=0x00000000 _Fillch=' ' } std::basic_ios<char,std::char_traits<char> > + std::ios_base {_Stdstr=0 _Mystate=0 _Except=0 ...} std::ios_base + _Mystrbuf 0x0037d758 {_Seekhigh=0x00b94dd4 "ýýýý««««««««" _Mystate=1 _Al={...} } std::basic_streambuf<char,std::char_traits<char> > * + _Tiestr 0x00000000 std::basic_ostream<char,std::char_traits<char> > * _Fillch 32 ' ' char _Chcount 0 __int64 _Val -9.2559631349317831e+061 double & + _Ok {_Ok=true } std::basic_istream<char,std::char_traits<char> >::sentry _State 0 int So I'm perplexed. Is this a stack or heap corruption problem? If so how does a local stringstream get into trouble? Any debugging hints are welcome.
All Replies
-
Monday, September 12, 2011 8:59 PM
On 9/12/2011 4:30 PM, Andrew7Webb wrote:
I'm looking for some helpful suggestions about how to debug this problem.
I get "First-chance exception at 0x01376e31 in InitUtil.exe: 0xC0000005: Access violation reading location 0x00000000."
Some background on the situation:
1) The code in the immediate area of the crash does work when called in very simple context, it only fails in a more complex situation.Look for heap corruption, likely in a seemingly unrelated piece of code.
So I'm perplexed. Is this a stack or heap corruption problem?
Heap corruption would be my guess.
If so how does a local stringstream get into trouble?
It allocates its own internal data structures on the heap.
Igor Tandetnik
-
Monday, September 12, 2011 9:25 PM
Thanks for pointing me towards heaps. I'll try some more debugging.
I added this at the start of the program._CrtSetDbgFlag( _CRTDBG_CHECK_ALWAYS_DF | _CRTDBG_CHECK_CRT_DF | _CRTDBG_DELAY_FREE_MEM_DF ); _ASSERTE( _CrtCheckMemory( ) );
and also one call in:
double getDouble( int id ) { _ASSERTE( _CrtCheckMemory( ) ); std::string text= getText( id ); std::stringstream ss ( text ); double retv; ss >> retv; return retv; }
But it did not result in any additional information. -
Tuesday, September 13, 2011 2:27 AM
But it did not result in any additional information.
Debugging access violations, heap corruption and memory leaks is a bit of an art form. The problem with access violations and heap corruption is that the faulty code may permit the program to run for a considerable period of time until it crashes in some innocent section.
My personal opinion is that a good code review, preferably with eyes other than your own, tends to be the most fruitful approach (and may uncover other unrelated problems to boot). Some material listed below may provide some help. If you come across other articles that are useful, I'd really like to hear from you so I can add it to my list.
Native Code: Heap Corruption/Memory Leaks Enable the Page Heap How to use the PageHeap utility to detect memory errors in a Microsoft Visual C++ project How to use Pageheap.exe in Windows XP, Windows 2000, and Windows Server 2003 Using Application Verifier to Troubleshoot Programs in Windows XP It is recommended to replace all occurrences of the unsafe buffer-copy APIs such as strcat, strcpy, or wcscpy with the secure ones like StringCchCopy, strcpy_s, and wcscpy_s, _mbscpy_s. You can use PREFast to find all unsafe uses of buffer-copy APIs, and replace them one by one. Memory Leak Detection Enabling Heap State Reporting Functions How can I Debug an Access Violation? Debugging Heap Corruption in Visual C++ Using Microsoft Debugging Tools For Windows Avoiding Buffer Overruns Debug Tutorial Part 3: The Heap -
Wednesday, September 14, 2011 9:50 PM
Looks like the problem was in the area of message loops with nested dialogs. I have to program around it for now.
This code
// Implement Win32 TRACE(...) // static void tracef( LPCTSTR lpszFormat, ... ) { #ifdef _DEBUG static const int BUFFERSIZE = 0x800; TCHAR lpszBuffer[BUFFERSIZE]; va_list fmtList; va_start( fmtList, lpszFormat ); _vstprintf_s( lpszBuffer, lpszFormat, fmtList ); va_end( fmtList ); ::OutputDebugString( lpszBuffer ); #endif }
helped me understand when things went wrong with sanity check variables.tracef( "promptedInputDialog: sanityCheck= %x\n", sanityCheck ); _ASSERTE( 0x123456 == sanityCheck ); -
Thursday, September 15, 2011 8:31 AMModerator
Hello,
Would you please upload a sample codes to skydriver? I think the codes your post here is no problem, maybe other codes cause this issue.
It is not necessary that you send out the whole of your project. We just need a simplest sample to reproduce the problem. You can remove any confidential information or business details from it.
Best regards,
Jesse
Jesse Jiang [MSFT]
MSDN Community Support | Feedback to us
Get or Request Code Sample from Microsoft
Please remember to mark the replies as answers if they help and unmark them if they provide no help.

-
Thursday, September 15, 2011 4:27 PM
The problem almost certainly was that my static library used /vmg
http://msdn.microsoft.com/en-us/library/aa243604(v=VS.60).aspx
and my main program did not do so.
Evidence: The problem went away after I removed the /vmg from my static library, and returned when I put it back.
I was using a static library that had a .props file I had forgotten about. I remembered it only when preparing a shrunk version to submit, and VS10 mentioned the path to the .props file was incorrect in the shrunk version. I actually made the same mistake 18 months ago and Lawrence Joel of Microsoft explained:
Crt headers contain some PTM (Pointers to Members) type functions, in our case ostream file has a few instances of this. One source file (stream_err.cpp) includes a .h with /vmg which later also includes CRT headers like ostream. The code generated for stream_err will have PTM implemented in the general representation. Another source file (application.cpp) does not include the pragma but has similar CRT headers. The code generated for application.cpp will have PTM implemented based on the compiler decisions (if compiler can find enough info on PTM then it will choose the best case, else choose general case).
The linker will take the obj files and will choose one of the PTM implementations (since their names and signature are the same). The Access Violation occurs because a routine will call the PTM routine assuming to have a return value represented in one way but it is represented in another way.
- Proposed As Answer by Jesse JiangMicrosoft Contingent Staff, Moderator Friday, September 16, 2011 6:44 AM
- Marked As Answer by Jesse JiangMicrosoft Contingent Staff, Moderator Monday, September 26, 2011 7:14 AM
-
Friday, September 16, 2011 6:45 AMModerator
Thanks for sharing the solution.
Best regards,
Jesse
Jesse Jiang [MSFT]
MSDN Community Support | Feedback to us
Get or Request Code Sample from Microsoft
Please remember to mark the replies as answers if they help and unmark them if they provide no help.


