使用MiniDumpWriteDump API 来生成程序的Dump
来源:互联网 发布:田岛7.0绣花软件 编辑:程序博客网 时间:2024/06/04 00:54
http://www.cnblogs.com/lzjsky/archive/2010/12/01/1893660.html
MiniDumpWriteDump是MS DbgHelp.dll 中一个API, 用于导出当前运行的程序的Dump. 这个dll程序系统中就有, 但是很多软件, 都在自己的安装目录下保存了这个.dll的最新的版本.
为了测试这个API, 参考网上一些资料, 写了一个简单的C++ 程序. 目的是当有异常发生的时候, 自动生成Dump文件供之后的分析. 有了Dump文件, 我们就可以使用WinDBG等调试器来分析异常发生时的情况. 其实这个功能很多软件都有, 比如QQ, 魔兽世界, 等等. 它们在出现了异常的时候会弹出一个对话框, 让用户输入异常发生时的情况, 然后把异常的dump文件用email发回, 供开发者们分析修改bug.
不过有一点, 这里需要程序的调试符号文件(pdb文件). 对于Debug版来说, 是生成的, 但是Release版来说默认是不生成的. 可以设置VC的编译器, 让它在Release版的时候也生成调试信息. 这带来一个新的问题, 因为.pdb里面是保存了源文件的信息的, 为了避免泄密, 可以采用VS中的CVPack工具, 从中去除敏感的信息.
程序需要使用Dbghelp.h 和 Dbghelp.lib . 它们可以从MSDN找到.
//最主要的函数, 生成Dump
static void DumpMiniDump(HANDLE hFile, PEXCEPTION_POINTERS excpInfo)
{
if (excpInfo == NULL) //如果没有传入异常, 比如是在程序里面调用的, 生成一个异常
{
// Generate exception to get proper context in dump
__try
{
OutputDebugString(_T("raising exception\r\n"));
RaiseException(EXCEPTION_BREAKPOINT, 0, 0, NULL);
}
__except(DumpMiniDump(hFile, GetExceptionInformation()),
EXCEPTION_CONTINUE_EXECUTION)
{
}
}
else
{
OutputDebugString(_T("writing minidump\r\n"));
MINIDUMP_EXCEPTION_INFORMATION eInfo;
eInfo.ThreadId = GetCurrentThreadId(); //把需要的信息添进去
eInfo.ExceptionPointers = excpInfo;
eInfo.ClientPointers = FALSE;
// 调用, 生成Dump. 98不支持
// Dump的类型是小型的, 节省空间. 可以参考MSDN生成更详细的Dump.
MiniDumpWriteDump(
GetCurrentProcess(),
GetCurrentProcessId(),
hFile,
MiniDumpNormal,
excpInfo ? &eInfo : NULL,
NULL,
NULL);
}
}
下面的是程序部分:
int _tmain(int argc, _TCHAR* argv[])
{
// 创建一个Dump文件
HANDLE hFile = CreateFile( _T("MiniDump.dmp"), GENERIC_READ | GENERIC_WRITE,
0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
int code;
__try
{
// 把自己实现的main函数包装一下, 放在try .. except 块中. 这样出现了异常可以自动生成dump
main_wrapper(argc, argv);
}
__except( code=GetExceptionCode(), DumpMiniDump(hFile, GetExceptionInformation() ), EXCEPTION_EXECUTE_HANDLER ) //出现了异常, 记录异常的code, 生成dump!!
{
printf("%x\n", code);
wchar_t msg[512];
wsprintf(msg, L"Exception happened. Exception code is %x", code);
MessageBox(NULL, msg, L"Exception", MB_OK); //显示消息给用户
}
CloseHandle( hFile ); //关闭Dump文件
getchar();
return 0;
}
最下面是两个测试的函数, main_wrapper函数将调用test1, test1将会生成一个异常(非法内存写)
void test1() {
int *p;
p = (int*)0x100;
*p = 0; //写0x100地址, 这个是非法的
}
void main_wrapper(int argc, _TCHAR* argv[]) {
test1();
}
运行, 异常被捕获了:
同时, dump文件也生成了:
用WinDBG打开Dump文件, 可以清楚的看出异常出现的情况:
从中可以比较清楚的看到异常发生的情况(Exception code), 异常出现的地址(test1函数, 偏移0x28). 因为这次测试的是Debug版, 有保存了源代码的.pdb文件, 所以WinDbg把源代码也列出来了. 这样可以非常容易的发现问题.
============================================
摘录自msdn
/****************************** Module Header ******************************\
Module Name: CppExceptionHandling.cpp
Project: CppExceptionHandling
Copyright (c) Microsoft Corporation.
- to be finished.
This source is subject to the Microsoft Public License.
See http://www.microsoft.com/opensource/licenses.mspx#Ms-PL.
All other rights reserved.
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
\***************************************************************************/
#include <stdio.h>
#include <tchar.h>
#include <windows.h>
#include <stdio.h>
#include <strsafe.h>
#include <shlwapi.h>
#include <dbghelp.h>
#pragma comment(lib, "Dbghelp.lib")
#pragma comment(lib, "shlwapi.lib")
// This method is to write mini dump of current process to
// CppExceptionHandling.dmp file.
LONG WINAPI WriteMiniDump(struct _EXCEPTION_POINTERS *ExceptionInfo)
{
// EXCEPTION_CONTINUE_SEARCH means it continue to
// execute subsequent exception handlers.
LONG rc = EXCEPTION_CONTINUE_SEARCH;
HMODULE hDll = NULL;
TCHAR szDumpFile[MAX_PATH];
StringCchPrintf(szDumpFile, MAX_PATH, _T("CppExceptionHandling.dmp"));
HANDLE hDumpFile;
hDumpFile = CreateFile(szDumpFile, GENERIC_WRITE, FILE_SHARE_WRITE, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hDumpFile != INVALID_HANDLE_VALUE)
{
MINIDUMP_EXCEPTION_INFORMATION ExInfo;
ExInfo.ThreadId = GetCurrentThreadId();
ExInfo.ExceptionPointers = ExceptionInfo;
ExInfo.ClientPointers = TRUE;
// Write the information into the dump
if (MiniDumpWriteDump(
GetCurrentProcess(), // Handle of process
GetCurrentProcessId(), // Process Id
hDumpFile, // Handle of dump file
MiniDumpNormal, // Dump Level: Mini
&ExInfo, // Exception information
NULL, // User stream parameter
NULL)) // Callback Parameter
{
rc = EXCEPTION_CONTINUE_SEARCH;
}
else
{
_tprintf(_T("MiniDumpWriteDump failed w/err 0x%08lx\n"), GetLastError());
}
CloseHandle(hDumpFile);
}
else
{
_tprintf(_T("CreateFile failed w/err 0x%08lx\n"), GetLastError());
}
return rc;
}
#pragma region Structured Exception
void ThrowStructuredException()
{
}
void ThrowAndHandleStructuredException()
{
}
#pragma endregion
#pragma region Vectored Exception
// The registered exception handler
LONG WINAPI VectoredExceptionHandler(struct _EXCEPTION_POINTERS *ExceptionInfo)
{
WriteMiniDump (ExceptionInfo);
printf("This vectored handler is always called first\n");
return EXCEPTION_CONTINUE_SEARCH;
}
void ThrowAndHandleVectoredException()
{
// Registers a vectored exception handler
PVOID handler = AddVectoredExceptionHandler(0, VectoredExceptionHandler);
// Raise a fake exception for demo
__try
{
printf("RaiseException: Raise an exception\n");
RaiseException(1,0,0,NULL);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
printf("This is a exception handler\n");
}
// Remove the vectored exception handler
RemoveVectoredExceptionHandler(handler);
}
#pragma endregion
int _tmain(int argc, _TCHAR* argv[])
{
ThrowAndHandleVectoredException();
return 0;
}
- 使用MiniDumpWriteDump API 来生成程序的Dump
- 使用MiniDumpWriteDump API 来生成程序的Dump
- 使用MiniDumpWriteDump API 来生成程序的Dump(转载)
- 使用MiniDumpWriteDump API 来生成程序的Dump
- 使用MiniDumpWriteDump API 来生成程序的Dump
- 使用MiniDumpWriteDump API 来生成程序的Dump
- 使用MiniDumpWriteDump API 来生成程序的Dump
- 使用MiniDumpWriteDump API 来生成程序的Dump
- 使用class-dump来生成iphone private api 头文件
- 生成dump的程序方法
- 生成程序崩溃的dump文件,使用windbg调试
- 生成程序崩溃的dump文件,使用windbg调试
- dump文件的生成和使用
- 如何用键盘来生成系统的dump文件
- MiniDumpWriteDump
- 使用phpdoc/phpDocumentor来生成api文档
- 利用 GDB & Core Dump 来定位程序出错的位置
- 程序崩溃 dump 文件 *.kdmp的使用
- java Swing 获取frame中的控件信息
- 机器学习笔记二十:拉格朗日函数/对偶
- 000031:将各变量隐式转换
- 百度统计
- 通用的进程监控脚本process_monitor.sh使用方法
- 使用MiniDumpWriteDump API 来生成程序的Dump
- SQLite学习手册(数据表和视图)
- 第二十三章 多项目集中权限管理及分布式会话——《跟我学Shiro》
- 'grep' 不是内部或外部命令,也不是可运行的程序 或批处理文件。
- DBCP 数据连接池的配置和使用
- lua table判空
- win32(2)--窗口创建
- SQLite学习手册(内置函数)
- Android动画(View Animation之Frame Animation(逐帧动画))