Reputation: 73503
I am using the following code to create a minidump file whenever there is a structured exception generated from my code:
void CreateMiniDump( EXCEPTION_POINTERS* pep )
{
// Open the file
typedef BOOL (*PDUMPFN)(
HANDLE hProcess,
DWORD ProcessId,
HANDLE hFile,
MINIDUMP_TYPE DumpType,
PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
PMINIDUMP_CALLBACK_INFORMATION CallbackParam
);
HANDLE hFile = CreateFile( _T("C:/temp/MiniDump.dmp"), GENERIC_READ | GENERIC_WRITE,
0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
HMODULE h = ::LoadLibrary(L"DbgHelp.dll");
PDUMPFN pFn = (PDUMPFN)GetProcAddress(h, "MiniDumpWriteDump");
if( ( hFile != NULL ) && ( hFile != INVALID_HANDLE_VALUE ) )
{
// Create the minidump
MINIDUMP_EXCEPTION_INFORMATION mdei;
mdei.ThreadId = GetCurrentThreadId();
mdei.ExceptionPointers = pep;
mdei.ClientPointers = TRUE;
MINIDUMP_TYPE mdt = MiniDumpNormal;
BOOL rv = (*pFn)( GetCurrentProcess(), GetCurrentProcessId(),
hFile, mdt, (pep != 0) ? &mdei : 0, 0, 0 );
// Close the file
CloseHandle( hFile );
}
}
LONG WINAPI MyUnhandledExceptionFilter(
struct _EXCEPTION_POINTERS *ExceptionInfo
)
{
CreateMiniDump(ExceptionInfo);
return EXCEPTION_EXECUTE_HANDLER;
}
And I am doing SetUnhandledExceptionFilter(MyUnhandledExceptionFilter);
from the main entry point of my app ( I am not setting it for each thread though). After this to test this code I did the following to generate an access violation: int* p = 0; *p = 0;
The dump file did get generated. Then I used windbg and opened the dump file and used .ecxr
command to get the exception record. However, no information is coming there (i.e. I am not getting the call stack). Also if I use !analyze -v
command then it is able to show the line where the crash occured. Does anybody know what I am missing and how to solve this?
BTW, I am using VC7 compiler with /EHa (asynchronuos exception model) flag.
Upvotes: 11
Views: 8848
Reputation: 85
However, no information is coming there (i.e. I am not getting the call stack)
.ecxr
isn't supposed to print a callstack, it's just supposed to set the context to that of the stored exception record - you'd want to do something like k 10
to actually print it. Or, since you're using WinDBG, open the callstack window.
(Maybe you're already doing this; I'm not sure from your description how .ecxr is failing - it should print something to let you know what it is / isn't able to do...)
Another thing to check is that you're actually getting exception pointers passed in - the code will generate a dump without them, but you'll get a funky callstack that way.
You mentioned in a comment on Alex's answer having some interference from a DLL overriding your filter with the runtime library's... This is a common problem. I've had good luck using the technique described by Oleg Starodumov:
There is one more approach possible, and it is much easier to implement than the previous two. After we have registered our own filter, we can patch the beginning of
SetUnhandledExceptionFilter
function so that it will not be able to register filters anymore.
He provides some handy example code for this purpose, which has served me well over the years.
Upvotes: 3
Reputation: 43331
Your code creating minidump is OK, the problem is post-mortem debugging. Debugger must have access to the program source code, .pdb files (which should be pdb files created when this program executable was built), and OS debugging symbols. Only having all this information, debugger can show exception place in the source code and call stack.
Post-mortem debugging process using Visual Studio debugger is described in details here: http://www.codeproject.com/KB/debug/postmortemdebug_standalone1.aspx For WinDbg, use Symbol, Source and Image file path to provide the same information for debugger.
Upvotes: 3