如何捕捉程序异常crash 并生成 dump 文件

如何捕捉程序异常crash 并生成 dump 文件,第1张

程序崩溃(crash)的时候, 为了以后能够调试分析问题, 可以使用WinDBG要把当时程序内存空间数据都保存下来,生成的文件称为dump 文件。

步骤:

1) 打开WinDBG并将之Attach 到crash的程序进程

2) 输入产生dump 文件的命令

WinDBG产生dump 文件的命令是 .dump ,可以选择不同的参数来生成不同类型的dump文件。

选项(1): /m

命令行示例:.dump /m C:\dumps\myapp.dmp

注解: 缺省选项,生成标准的minidump, 转储文件通常较小,便于在网络上通过邮件或其他方式传输。 这种文件的信息量较少,只包含系统信息、加载的模块(DLL)信息、 进程信息和线程信息。

选项(2): /ma

命令行示例:.dump /ma C:\dumps\myapp.dmp

注解: 带有尽量多选项的minidump(包括完整的内存内容、句柄、未加载的模块,等等),文件很大,但如果条件允许(本机调试,局域网环境), 推荐使用这中dump。

选项(3):/mFhutwd

命令行示例:.dump /mFhutwd C:\dumps\myapp.dmp

注解:带有数据段、非共享的读/写内存页和其他有用的信息的minidump。包含了通过minidump能够得到的最多的信息。是一种折中方案。

上面介绍如如何用WinDBG 生成crash dump 《WinDBG 技巧:如何生成Dump 文件(.dump 命令) 》,但是用户机器上通常不安装WinDBG, 而且多数用户也不知道怎么使用WinDBG。 所以最好是自己程序里面能够捕捉exception/crash,并且生成crash dump,然后通过网络传回到自己服务器。

捕捉exception 可以用API 函数 SetUnhandledExceptionFilter 。

生成crash dump 可以用DbgHelp.dll 里面的MiniDumpWriteDump 函数。

LPTOP_LEVEL_EXCEPTION_FILTER WINAPI SetUnhandledExceptionFilter( __in LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter )

BOOL WINAPI MiniDumpWriteDump( __in HANDLE hProcess, __in DWORD ProcessId, __in HANDLE hFile, __in MINIDUMP_TYPE DumpType, __in PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, __in PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, __in PMINIDUMP_CALLBACK_INFORMATION CallbackParam )

【代码实例】

#include <dbghelp.h>

#include <shellapi.h>

#include <shlobj.h>

// 自定义的exectpion filter

LONG WINAPI MyUnhandledExceptionFilter(struct _EXCEPTION_POINTERS*pExceptionPointers)

{

SetErrorMode( SEM_NOGPFAULTERRORBOX )

//收集信息

CStringW strBuild

strBuild.Format(L"Build: %s %s", __DATE__, __TIME__)

CStringW strError

HMODULE hModule

WCHAR szModuleName[MAX_PATH] = L""

GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,(LPCWSTR)pExceptionPointers->ExceptionRecord->ExceptionAddress,&hModule)

GetModuleFileName(hModule, szModuleName, ARRAYSIZE(szModuleName))

strError.AppenedFormat(L"%s %d , %d ,%d.",szModuleName,pExceptionPointers->ExceptionRecord->ExceptionCode,pExceptionPointers->ExceptionRecord->ExceptionFlags,pExceptionPointers->ExceptionRecord->ExceptionAddress)

//生成 mini crash dump

BOOL bMiniDumpSuccessful

WCHAR szPath[MAX_PATH]

WCHAR szFileName[MAX_PATH]

WCHAR* szAppName = L"AppName"

WCHAR* szVersion = L"v1.0"

DWORD dwBufferSize = MAX_PATH

HANDLE hDumpFile

SYSTEMTIME stLocalTime

MINIDUMP_EXCEPTION_INFORMATION ExpParam

GetLocalTime( &stLocalTime )

GetTempPath( dwBufferSize, szPath )

StringCchPrintf( szFileName, MAX_PATH, L"%s%s", szPath, szAppName)

CreateDirectory( szFileName, NULL )

StringCchPrintf( szFileName, MAX_PATH, L"%s%s\\%s-%04d%02d%02d-%02d%02d%02d-%ld-%ld.dmp",

szPath, szAppName, szVersion,

stLocalTime.wYear, stLocalTime.wMonth, stLocalTime.wDay,

stLocalTime.wHour, stLocalTime.wMinute,stLocalTime.wSecond,

GetCurrentProcessId(), GetCurrentThreadId())

hDumpFile = CreateFile(szFileName, GENERIC_READ|GENERIC_WRITE,

FILE_SHARE_WRITE|FILE_SHARE_READ, 0, CREATE_ALWAYS, 0,0)

MINIDUMP_USER_STREAM UserStream[2]

MINIDUMP_USER_STREAM_INFORMATION UserInfo

UserInfo.UserStreamCount = 1

UserInfo.UserStreamArray = UserStream

UserStream[0].Type = CommentStreamW

UserStream[0].BufferSize = strBuild.GetLength()*sizeof(WCHAR)

UserStream[0].Buffer = strBuild.GetBuffer()

UserStream[1].Type = CommentStreamW

UserStream[1].BufferSize = strError.GetLength()*sizeof(WCHAR)

UserStream[1].Buffer = strError.GetBuffer()

ExpParam.ThreadId = GetCurrentThreadId()

ExpParam.ExceptionPointers = pExceptionPointers

ExpParam.ClientPointers = TRUE

MINIDUMP_TYPE MiniDumpWithDataSegs = MiniDumpNormal

| MiniDumpWithHandleData

| MiniDumpWithUnloadedModules

| MiniDumpWithIndirectlyReferencedMemory

| MiniDumpScanMemory

| MiniDumpWithProcessThreadData

| MiniDumpWithThreadInfo

bMiniDumpSuccessful = MiniDumpWriteDump(GetCurrentProcess(),GetCurrentProcessId(),

hDumpFile, MiniDumpWithDataSegs, &ExpParam, NULL,NULL)

// 上传mini dump 到自己服务器(略)

...

return EXCEPTION_CONTINUE_SEARCH//或者 EXCEPTION_EXECUTE_HANDLER 关闭程序

}

int _tmain()

{

// 设置 execption filter

SetUnhandledExceptionFilter(MyUnhandledExceptionFilter)

....

return 0

}

正常情况下不会生成dump,需要自己在程序中添加代码实现,一般是利用MS的dbghelp.dll提供的DbgHelpCreateUserDump来生成,用WinDbg来分析,期间需要编译程序生成的.pdb文件。可以参考BlackBox、google breakpad等

crash 文件生成的路径:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug]

"Auto"="0"

"Debugger"="\"D:\\WinDBG\\ntsd.exe\" -p %ld -e %ld -g -noio -c \".dump /ma /u d:\\dbgdmp\\dmp.dmpq"

"UserDebuggerHotKey"=dword:00000000

转载仅供参考,版权属于原作者。祝你愉快,满意请采纳哦

iOS开发中遇到程序崩溃是很正常的事情,如何在程序崩溃时捕获到异常信息并通知开发者?

下面就介绍如何在iOS中实现:

1. 在程序启动时加上一个异常捕获监听,用来处理程序崩溃时的`回调动作

复制代码 代码如下:

NSSetUncaughtExceptionHandler (&UncaughtExceptionHandler)

官方文档介绍:Sets the top-level error-handling function where you can perform last-minute logging before the program terminates.

UncaughtExceptionHandler是一个函数指针,该函数需要我们实现,可以取自己想要的名字。当程序发生异常崩溃时,该函数会得到调用,这跟C,C++中的回调函数的概念是一样的。

2. 实现自己的处理函数

复制代码 代码如下:

void UncaughtExceptionHandler(NSException *exception) {

NSArray *arr = [exception callStackSymbols]//得到当前调用栈信息

NSString *reason = [exception reason]//非常重要,就是崩溃的原因

NSString *name = [exception name]//异常类型

NSLog(@"exception type : %@ n crash reason : %@ n call stack info : %@", name, reason, arr)

}

以上代码很简单,但是带来的作用是非常大的。

Android系统的“程序异常退出”,给应用的用户体验造成不良影响。为了捕获应用运行时异常并给出友好提示,便可继承UncaughtExceptionHandler类来处理。通过Thread.setDefaultUncaughtExceptionHandler()方法将异常处理类设置到线程上即可。

1、异常处理类,代码如下:

[java] view plaincopy

public class CrashHandler implements UncaughtExceptionHandler {

public static final String TAG = "CrashHandler"

private static CrashHandler INSTANCE = new CrashHandler()

private Context mContext

private Thread.UncaughtExceptionHandler mDefaultHandler

private CrashHandler() {

}

public static CrashHandler getInstance() {

return INSTANCE

}

public void init(Context ctx) {

mContext = ctx

mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler()

Thread.setDefaultUncaughtExceptionHandler(this)

}

@Override

public void uncaughtException(Thread thread, Throwable ex) {

// if (!handleException(ex) &&mDefaultHandler != null) {

// mDefaultHandler.uncaughtException(thread, ex)

// } else {

// android.os.Process.killProcess(android.os.Process.myPid())

// System.exit(10)

// }

System.out.println("uncaughtException")

new Thread() {

@Override

public void run() {

Looper.prepare()

new AlertDialog.Builder(mContext).setTitle("提示").setCancelable(false)

.setMessage("程序崩溃了...").setNeutralButton("我知道了", new OnClickListener() {

@Override

public void onClick(DialogInterface dialog, int which) {

System.exit(0)

}

})

.create().show()

Looper.loop()

}

}.start()

}

/**

* 自定义错误处理,收集错误信息 发送错误报告等 *** 作均在此完成. 开发者可以根据自己的情况来自定义异常处理逻辑

*

* @param ex

* @return true:如果处理了该异常信息否则返回false

*/

private boolean handleException(Throwable ex) {

if (ex == null) {

return true

}

// new Handler(Looper.getMainLooper()).post(new Runnable() {

// @Override

// public void run() {

// new AlertDialog.Builder(mContext).setTitle("提示")

// .setMessage("程序崩溃了...").setNeutralButton("我知道了", null)

// .create().show()

// }

// })

return true

}

}

2、线程绑定异常处理类

[java] view plaincopy

public class CrashHandlerActivity extends Activity {

/** Called when the activity is first created. */

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState)

setContentView(R.layout.main)

CrashHandler crashHandler = CrashHandler.getInstance()

crashHandler.init(this) //传入参数必须为Activity,否则AlertDialog将不显示。

// 创建错误

throw new NullPointerException()

}

}


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/12077734.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-20
下一篇 2023-05-20

发表评论

登录后才能评论

评论列表(0条)

保存