How to Use Windbg to Analyze the Crash Dump for Vc++ Application

How to use WinDbg to analyze the crash dump for VC++ application?

Here are some general steps that will get you on your way:

First, you must change your compiler's settings so that it creates PDB files, even for release builds. Later versions of the Visual C++ compiler do this by default, but in many versions of Visual C++ you must do this yourself. Create program database files, and then keep an archive of those files along with each build of your application. It is critical that every build of your applications has its own set of PDBs. You can't just reuse the same ones you made with build 10 to examining the dumps generated by build 15, for example. Over the life of your project, you will end up with a ton of PDBs, so be prepared for that.

Next, you need to be able to identify the exact version of your application which generated the dump file. If you are creating your own MiniDumps (by calling MiniDumpWriteDump() for example), probably the easiest way to do this is to simply make part of the filename of the MiniDump the complete version number of your application. You'll need to have a reasonable version numbering scheme in place for this to work. In my shop, we increment the build number across all branches by one every time the autobuilder creates a build.

Now that you have received the dump file from the customer, you know the precise version of the application that created the dump, and you have found the PDB files for this build.

Now you need to go through your source control's history and find the source code for this exact version of the software. The best way to do this is to apply 'labels' to your branches every time you make a build. Set the value of the label to the exact version number, and it becomes easy to find in the history.

You're almost ready to fire up WinDbg/Visual C++:

  1. Get the complete source tree for that version of your application. Put it in a separate place on your hard drive, say c:\app_build_1.0.100 for application version 1.0 build #100.
  2. Get the binaries for that exact version of your application and put them somewhere on your hard drive. It might be easiest simply to install that version of your application to get the binaries.
  3. Put the PDB files in the same location as the binaries in step 2.

Now you have two options for viewing the dump file. You can use Visual Studio or WinDbg. Using Visual Studio is easier, but WinDbg is much more powerful. Most of the time the functionality in Visual Studio will suffice.

To use Visual Studio, all you have to do is open the dump file like it is a project. Once opened, "run" the dump file (F5 by default) and if all the paths are set correctly it will take you right to the code that crashed, give you a call stack, etc.

To use WinDbg, you have to jump through a couple of hoops:

  1. Start WinDbg
  2. Open the dump file. (Ctrl + D by default)
  3. Tell WinDbg to go get the correct MicroSoft symbol files. Type .symfix. This may take a few moments as it will pull a ton of stuff down from the Internet.
  4. Tell WinDbg where the symbols (PDB files) are. Type .sympath+ c:\pdblocation, substituting wherever you put the PDB files for the pathname. Make sure you get the plus sign in there with no whitespace between .sympath and the + sign or else you'll screw up step 3.
  5. Tell WinDbg where the source code is. Type .srcpath c:\app_build_1.0.100 substituting the path where you got code from source control for this version of the software.
  6. Tell WinDbg to analyze the dump file. Type !analyze -v

After a few moments, if everything is configured correctly, WinDbg will take you right to the location of your crash. At this point you have a million options for digging deep into your application's memory space, the state of critical sections, windows, etc. But that is way beyond the scope of this post.

Good luck!

How to write a sample code that will crash and produce dump file?

#include <Windows.h>
#include <Dbghelp.h>

void make_minidump(EXCEPTION_POINTERS* e)
{
auto hDbgHelp = LoadLibraryA("dbghelp");
if(hDbgHelp == nullptr)
return;
auto pMiniDumpWriteDump = (decltype(&MiniDumpWriteDump))GetProcAddress(hDbgHelp, "MiniDumpWriteDump");
if(pMiniDumpWriteDump == nullptr)
return;

char name[MAX_PATH];
{
auto nameEnd = name + GetModuleFileNameA(GetModuleHandleA(0), name, MAX_PATH);
SYSTEMTIME t;
GetSystemTime(&t);
wsprintfA(nameEnd - strlen(".exe"),
"_%4d%02d%02d_%02d%02d%02d.dmp",
t.wYear, t.wMonth, t.wDay, t.wHour, t.wMinute, t.wSecond);
}

auto hFile = CreateFileA(name, GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
if(hFile == INVALID_HANDLE_VALUE)
return;

MINIDUMP_EXCEPTION_INFORMATION exceptionInfo;
exceptionInfo.ThreadId = GetCurrentThreadId();
exceptionInfo.ExceptionPointers = e;
exceptionInfo.ClientPointers = FALSE;

auto dumped = pMiniDumpWriteDump(
GetCurrentProcess(),
GetCurrentProcessId(),
hFile,
MINIDUMP_TYPE(MiniDumpWithIndirectlyReferencedMemory | MiniDumpScanMemory),
e ? &exceptionInfo : nullptr,
nullptr,
nullptr);

CloseHandle(hFile);

return;
}

LONG CALLBACK unhandled_handler(EXCEPTION_POINTERS* e)
{
make_minidump(e);
return EXCEPTION_CONTINUE_SEARCH;
}

int main()
{
SetUnhandledExceptionFilter(unhandled_handler);

return *(int*)0;
}

How to analyze Crash Dump using WinDbg

The stack that you get from !analyze -v does not look reliable. All the functions in the stack are same : 'System_ni!System.Net.Mail.SmtpClient.Send(System.Net.Mail.MailMessage)+0x216fe7'

Unless you are hitting an infinite recursion, within that function! ?

My 2 cents
a. Please load symbols
For stack over flow exceptions the faulting stack it self generally points to the culprit. But without symbols it will be very difficult to make out.
b. Take a look at the stack of all threads. You may get some further pointers.

WinDbg to analyze the crash dump doesn't work on the local pc

You will need the same pdbs without private symbols removed accessible from your laptop in order to get sensible call stacks with correct source line information, also I notice you seem to have cached some symbols to c:\symbols are these the same and also resolve the windows symbols?

Check your visual c++ settings to make sure that you are not stripping private symbols from the pdbs, it will most likely warn you when you try to set breakpoints, search symbols or perform a crash analysis by stating that it was unable to verify the checksum or similar message.

I also notice you are running your app on a 64 bit server and then on a 32 bit laptop, are you running the correct version of WinDbg is my next question, there are 32 and 64 bit versions.

Also what version of windbg are you using? There are often bugs with various versions so you may want to check you are running the same version on your laptop as on your server.

Understand Crash Dump from Visual C++ App

DbgBreakPoint -- Looks to me like you broke execution using a remote debugger.

If you didn't then I have seen DbgBreakPoint show up when you have code pages (Edit: I meant page heap) turned on (you should know if you did this) and there was a detection of invalid memory access.

Performance Counters in Windbg Crash Dump

No, it not possible to see the values of the counters because are not stored in the c++ application address space. All you may extract from the dump are the thread ids, user time, kernel time and elapsed time (see the !runaway command).

Windows application crash .dmp file analysis in visual studio

From what I remembered, VS6 cannot be used to debug dumps. It's been a while since I last used it, and trying to verify me memory I came across a workaround that might allow you to debug those dumps after all: Visual C++ 6, and post-mortem (crash dump) debugging.

I don't have VC6 at hand, and have no idea if this really works. Other than that, I feel for you... There are IDEs so much better than VC6. Hope this inability gives you the push towards an upgrade. Debugging dumps is really easy with VC7 and above.



Related Topics



Leave a reply



Submit