使用 dbghelp.dll 进行 Release 除虫

参考: http://blog.csdn.net/ArCoolGG/archive/2007/04/05/1553027.aspx 

首先,写一个 异常处理函数。

std::ostream& operator << ( std::ostream& os, const EXCEPTION_RECORD& red )
{  //  
 return os << "   Thread ID:" << GetCurrentThreadId()
  << "   ExceptionCode: " << red.ExceptionCode << "/n"
  << "   ExceptionFlags: " << red.ExceptionFlags << "/n"
  << "   ExceptionAddress: " << red.ExceptionAddress << "/n"
  << "   NumberParameters: " << red.NumberParameters;
}

// 这个处理函数调用 Nick  的 minidump 创建 dmp 文件。

#include "minidump.h"
LONG __stdcall MyUnhandledExceptionFilter(PEXCEPTION_POINTERS pExceptionInfo)
{
 CreateMiniDump( pExceptionInfo, "myproject.dmp" );
 std::cerr << " 未知错误: " << (*pExceptionInfo->ExceptionRecord ) << std::endl;
 exit( pExceptionInfo->ExceptionRecord->ExceptionCode  );
 return EXCEPTION_EXECUTE_HANDLER;
}

然后在 main 函数开始的时候(只要在异常发生之前)调用 api

SetUnhandledExceptionFilter(MyUnhandledExceptionFilter);

把 未捕获的异常(主要应该是飞指针造成的) 传送给 我们的 MyUnhandledExceptionFilter 函数来处理, 而不是由操作系统弹出那个让人不知所云的非法错误提示窗口。

这些代码会帮助你创建一个 dmp 文件,把这个文件和编译时产生的 exe, pdb 文件放在一起,然后使用 vs 2005 或者 dmp 处理工具打开,就可以直接定位到错误发生时执行的代码,还包括堆栈和有限的变量信息(别相信 this 是0,this 在dmp中永远显示0)。

注意:exe 必须能找到 dbghelp.dll 才能正确生成 dmp 文件,这个 dll 你可以从微软的 dbghelp.dll Debugging Tools for Windows 工具中找到,dbghelp.lib 在 vs 2005 中有,否则你可以去 Windows SDK 中找。

当异常代码定位成功以后,如果无法阻止异常的产生,可以用 __try 结构包装异常代码,__try 和 try 不同,前者可以捕获非法指针产生的异常。

__try{
// 会异常的函数
} __except( EXCEPTION_EXECUTE_HANDLER ){
// 异常处理
}

 附 minidmp.h

/* Nico 07-4-5 1027
 quoted from minidump.cpp@debuginfo.com
 */

#pragma once
#include <windows.h>
#include <imagehlp.h>
#pragma comment(lib, "dbghelp.lib")


inline bool IsDataSectionNeeded( const WCHAR* pModuleName )
{
 if( pModuleName == 0 )
 {
  return false;
 }

 WCHAR szFileName[_MAX_FNAME] = L"";
 _wsplitpath( pModuleName, NULL, NULL, szFileName, NULL );

 if( wcsicmp( szFileName, L"ntdll" ) == 0 ) return true;
 return false;
}

inline BOOL CALLBACK MiniDumpCallback(
 PVOID                            pParam,
 const PMINIDUMP_CALLBACK_INPUT   pInput,
 PMINIDUMP_CALLBACK_OUTPUT        pOutput
)
{
 if( pInput == 0 || pOutput == 0) return FALSE;
 switch( pInput->CallbackType )
 {
  case ModuleCallback:
   if( pOutput->ModuleWriteFlags & ModuleWriteDataSeg )
    if( !IsDataSectionNeeded( pInput->Module.FullPath ) )
     pOutput->ModuleWriteFlags &= (~ModuleWriteDataSeg);
   // fall through
  case IncludeModuleCallback:
  case IncludeThreadCallback:
  case ThreadCallback:
  case ThreadExCallback:
   return TRUE;
 default:;
 }
 return FALSE;
}

inline void CreateMiniDump( EXCEPTION_POINTERS* pep, LPCSTR filename)
{
 HANDLE hFile = CreateFile( filename, GENERIC_READ | GENERIC_WRITE,
  0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );

 if( ( hFile != NULL ) && ( hFile != INVALID_HANDLE_VALUE ) )
 {
  MINIDUMP_EXCEPTION_INFORMATION mdei;
  mdei.ThreadId           = GetCurrentThreadId();
  mdei.ExceptionPointers  = pep;
  mdei.ClientPointers     = FALSE;
  MINIDUMP_CALLBACK_INFORMATION mci;
  mci.CallbackRoutine     = (MINIDUMP_CALLBACK_ROUTINE)MiniDumpCallback;
  mci.CallbackParam       = 0;
  MINIDUMP_TYPE mdt       = (MINIDUMP_TYPE)(MiniDumpWithPrivateReadWriteMemory |
                                            MiniDumpWithDataSegs |
                                            MiniDumpWithHandleData |
                                            0x00000800 /*MiniDumpWithFullMemoryInfo*/ |
                                            0x00001000 /*MiniDumpWithThreadInfo*/ |
                                            MiniDumpWithUnloadedModules );
  MiniDumpWriteDump( GetCurrentProcess(), GetCurrentProcessId(),
   hFile, mdt, (pep != 0) ? &mdei : 0, 0, &mci );

  CloseHandle( hFile );
 }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值