以编程方式生成的 Windbg 转储无法调试
我有一个简单的程序:
int ExecuteCommand(wchar_t* commandLine)
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
BOOL bRet;
DWORD lpExitCode;
memset(&si, 0, sizeof(si));
si.cb = sizeof(si);
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_HIDE;
bRet = CreateProcess(
NULL, // pointer to name of executable module
commandLine, // pointer to command line string
NULL, // process security attributes
NULL, // thread security attributes
FALSE, // handle inheritance flag
NORMAL_PRIORITY_CLASS, // creation flags
NULL, // pointer to new environment block
NULL, // pointer to current directory name
&si, // pointer to STARTUPINFO
&pi // pointer to PROCESS_INFORMATION
);
if(bRet) WaitForSingleObject(pi.hProcess, INFINITE); // wait for process to finish
GetExitCodeProcess(pi.hProcess, &lpExitCode);
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
return lpExitCode;
}
void CreateCoreDump()
{
wchar_t buffer[256];
wsprintf(buffer, _T("windbg -p %d -c \".dump /mfh /u C:\\Tmp\\crashdump.dmp\""), GetCurrentProcessId());
ExecuteCommand(buffer);
}
DWORD ExceptionFilter()
{
CreateCoreDump();
return EXCEPTION_CONTINUE_SEARCH;
}
int _tmain(int argc, _TCHAR* argv[])
{
__try
{
int* p = NULL;
*p = 100;
}
__except(ExceptionFilter())
{
}
return 0;
}
当出现异常时,它将使用函数 CreateCoreDump 生成核心转储。虽然可以成功生成转储文件,但似乎没什么用:
如果我使用windbg打开这个转储文件,调用堆栈中没有任何内容!!!
但是,如果我直接在windbg中调试这个应用程序,并在调用CreateCoreDump的行设置断点,然后运行windbg命令:
.dump /mfh C:\Tmp\mydump.dmp
用WinDbg打开这个转储文件,我可以看到完整的调用堆栈。
我在生成转储文件或使用 Windbg 调试转储文件时是否做错了什么?
I have a simple program:
int ExecuteCommand(wchar_t* commandLine)
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
BOOL bRet;
DWORD lpExitCode;
memset(&si, 0, sizeof(si));
si.cb = sizeof(si);
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_HIDE;
bRet = CreateProcess(
NULL, // pointer to name of executable module
commandLine, // pointer to command line string
NULL, // process security attributes
NULL, // thread security attributes
FALSE, // handle inheritance flag
NORMAL_PRIORITY_CLASS, // creation flags
NULL, // pointer to new environment block
NULL, // pointer to current directory name
&si, // pointer to STARTUPINFO
&pi // pointer to PROCESS_INFORMATION
);
if(bRet) WaitForSingleObject(pi.hProcess, INFINITE); // wait for process to finish
GetExitCodeProcess(pi.hProcess, &lpExitCode);
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
return lpExitCode;
}
void CreateCoreDump()
{
wchar_t buffer[256];
wsprintf(buffer, _T("windbg -p %d -c \".dump /mfh /u C:\\Tmp\\crashdump.dmp\""), GetCurrentProcessId());
ExecuteCommand(buffer);
}
DWORD ExceptionFilter()
{
CreateCoreDump();
return EXCEPTION_CONTINUE_SEARCH;
}
int _tmain(int argc, _TCHAR* argv[])
{
__try
{
int* p = NULL;
*p = 100;
}
__except(ExceptionFilter())
{
}
return 0;
}
It will generate a core dump when there is an exception, using function CreateCoreDump. Although the dump file could be generated successfully, it seems useless:
If I open this dump file using windbg, there is nothing in call stack!!!
But, if I debug this application directly in windbg, and set breakpoint at the line of calling CreateCoreDump, and then run windbg command:
.dump /mfh C:\Tmp\mydump.dmp
Open this dump file with WinDbg, I can see the full call stack.
Did I do something wrong, either in generating the dump file, or debugging the dump file using windbg?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
当异常发生后附加调试器时,调试器不会看到异常事件。它创建一个具有断点的线程,因此该线程上的堆栈看起来像这样:
如果您手动将当前线程设置为线程 0(使用
~0s
),您将看到堆栈当您启动调试器下的程序会发生两件事,第一,只有一个线程,第二调试器知道异常,因此它会打印如下内容:
它告诉您需要使用
.ecxr
命令进入有趣的线程。在这种情况下,您不需要这样做,因为当前的调试器线程已经是您想要的线程。When you attach the debugger after the exception happens, the debugger does not see the exception event. It creates a thread that has a breakpoint so the stack on that thread looks something like this:
If you manually set the current thread to thread 0 (use
~0s
) you will see your stackWhen you start your program under the debugger two things happen, first, there is only one thread, and second the debugger knows about the exception so it will print something like this:
which tells you that you need to use the
.ecxr
commmand to get to the interesting thread. In this case you do not need to because the current debugger thread is already the one you want.您必须将异常记录添加到转储中。例如,我更改了您的示例以检索过滤器中的异常信息,并在生成转储时将其传递到命令行。
然后,当您在 Windgb 中打开转储时,调试器就会知道异常事件。您可以使用
.ecxr
设置异常点处的当前线程和堆栈。You have to add the exception record to the dump. For instance, I changed your sample to retrieve the exception information in the filter and pass it on the command line when generating the dump.
Then when you open the dump in windgb, the debugger knows about the exception event. You can use
.ecxr
to set the current thread and stack at the exception point.