iOS Crash闪退信息捕获工具类

IOS SDK中提供了一个现成的函数 NSSetUncaughtExceptionHandler 用来做异常处理,但功能非常有限,而引起崩溃的大多数原因如:内存访问错误,重复释放等错误捕获不到,因为这些异常抛出的是Signal,所以必须要专门做Signal处理。工具类的实现源码如下:

头文件

#import <Foundation/Foundation.h>

extern NSString *const UncaughtExceptionHandlerSignalKey;
extern NSString *const SingalExceptionHandlerAddressesKey;
extern NSString *const ExceptionHandlerAddressesKey;

@interface ExceptionHandler : NSObject
+ (void)installExceptionHandler;
+ (NSArray *)backtrace;
@end

实现文件

#import "ExceptionHandler.h"
#include <libkern/OSAtomic.h>
#include <execinfo.h>

NSString *const UncaughtExceptionHandlerSignalKey = @"UncaughtExceptionHandlerSignalKey";
NSString *const SingalExceptionHandlerAddressesKey = @"SingalExceptionHandlerAddressesKey";
NSString *const ExceptionHandlerAddressesKey = @"ExceptionHandlerAddressesKey";

const int32_t _uncaughtExceptionMaximum = 20;

// 系统信号截获处理方法
void signalHandler(int signal);

// 异常截获处理方法
void exceptionHandler(NSException *exception);

void signalHandler(int signal)
{
    volatile int32_t _uncaughtExceptionCount = 0;
    int32_t exceptionCount = OSAtomicIncrement32(&_uncaughtExceptionCount);

    // 如果太多不用处理
    if (exceptionCount > _uncaughtExceptionMaximum) {
        return;
    }

    // 获取信息
    NSMutableDictionary *userInfo = [NSMutableDictionary dictionaryWithObject:[NSNumber numberWithInt:signal] forKey:UncaughtExceptionHandlerSignalKey];
    NSArray *callStack = [ExceptionHandler backtrace];
    [userInfo  setObject:callStack  forKey:SingalExceptionHandlerAddressesKey];

    // 现在就可以保存信息到本地[]

}

void exceptionHandler(NSException *exception)
{
    volatile int32_t _uncaughtExceptionCount = 0;
    int32_t exceptionCount = OSAtomicIncrement32(&_uncaughtExceptionCount);

    // 如果太多不用处理
    if (exceptionCount > _uncaughtExceptionMaximum) {
        return;
    }

    NSArray *callStack = [ExceptionHandler backtrace];
    NSMutableDictionary *userInfo =[NSMutableDictionary dictionaryWithDictionary:[exception userInfo]];
    [userInfo setObject:callStack forKey:ExceptionHandlerAddressesKey];
    NSLog(@"Exception Invoked: %@", userInfo);

    // 现在就可以保存信息到本地[]

}

@implementation ExceptionHandler

//获取调用堆栈
+ (NSArray *)backtrace
{
    void* callstack[128];
    int frames = backtrace(callstack, 128);
    char **strs = backtrace_symbols(callstack,frames);

    NSMutableArray *backtrace = [NSMutableArray arrayWithCapacity:frames];
    for (int i=0;i<frames;i++) {
        [backtrace addObject:[NSString stringWithUTF8String:strs[i]]];
    }
    free(strs);
    return backtrace;
}

// 注册崩溃拦截
+ (void)installExceptionHandler
{
    NSSetUncaughtExceptionHandler(&exceptionHandler);
    signal(SIGHUP, signalHandler);
    signal(SIGINT, signalHandler);
    signal(SIGQUIT, signalHandler);
    signal(SIGABRT, signalHandler);
    signal(SIGILL, signalHandler);
    signal(SIGSEGV, signalHandler);
    signal(SIGFPE, signalHandler);
    signal(SIGBUS, signalHandler);
    signal(SIGPIPE, signalHandler);
}

@end
时间: 2024-10-05 18:10:38

iOS Crash闪退信息捕获工具类的相关文章

ios Crash闪退日志获取和上传至服务器

最近客户有个要求:人家谁谁有crash日志捕获和上传,我们是不是也要做一个...  人家谁谁.....还有什么什么功能........ 正好最近也在研究这方面东东,所以整理一下分享给大家:如何用程序获取Crash日志 并 可以上传Crash日志. 首先我们整理经常会闪退的异常哪些:数组越界.空引用.引用未定义方法.内存空间不足等等. 友盟分享后台是可以看到crash的日志,如下图: 开始研究的时候,我有两个疑问: 1.如何获取crash闪退日志(工具和程序两种方法): 2.解析crash: 说明

iOS开发项目篇—21抽取工具类

iOS开发项目篇—21抽取工具类 一.抽取宏 把和应用相关的信息抽取出来 App Key:1972915028 App Secret:b255603c4dfd82b4785bf9a808ce2662 回调地址:http://www.cnblogs.com/wendingding/ (1)appkey和回调页面在很多地方都要用到 (2)如果是不同应用的话,只需要把这几个参数换掉就可以了.把它们抽取成一个宏,写到pch文件中. 项目的PCH文件 1 #import <Availability.h>

iOS开发-闪退问题-解决之前上架的 App 在 iOS 9 会闪退问题

最新更新:(2015.10.02) 开发环境: Delphi 10 Seattle OS X El Capitan v10.11 需使用下列 HotfixID: 30398, PAServer Hotfix for Delphi, C++Builder and RAD Studio 10 Seattle Xcode v7.0.1 iOS SDK v9.0 真机测试(以下机种皆不闪退): iPhone 3GS v6.1.2 (32 bit) iPhone 4 v7.1.2 (32 bit) iPh

系统内存信息获取工具类

/** * 得到系统内存信息的工具类 * @author zwenkai */ public class SystemInfoUtils { /** * 得到运行的进程总个数 * * @param context * @return 运行进程个数 */ public static int getRunningProcessCount(Context context) { ActivityManager am = (ActivityManager) context.getSystemService

获取SIM卡信息的工具类

本工具类可以获取手机的IMSI.本机的手机号码.SIM卡的服务商. 移动.联通可正常获取到SIM卡的手机卡号,但是电信的获取不到.... 首先,需要在AndroidManifest.xml清单配置文件中添加权限: <uses-permission android:name="android.permission.READ_PHONE_STATE"/> 下面是工具类的代码 SIMCardInfo.java import android.content.Context; imp

避免SIGPIPE导致的iOS应用闪退/Avoiding SIGPIPE signal crash in iOS(mach_msg_trap、SIGPIPE信号)

问题描述: 应用运行时,锁屏后再打开有一定几率闪退.通过真机调试发现程序会中断在此处: libsystem_kernel.dylib`mach_msg_trap: 解决思路: 通过这篇文章了解是进程收到 SIGPIPE  信号,该信号默认行为是终止进程. The process received a SIGPIPE . The default behaviour for this signal is to end the process. A SIGPIPE is sent to a proce

Android设备网络、屏幕尺寸、SD卡、本地IP、存储空间等信息获取工具类

Android设备网络.屏幕尺寸.SD卡.本地IP.存储空间.服务.进程.应用包名等信息获取的整合工具类. 1 package com.qiyu.ddb.util; 2 3 import android.annotation.SuppressLint; 4 import android.annotation.TargetApi; 5 import android.app.Activity; 6 import android.app.ActivityManager; 7 import androi

分享一个用OnGUI在手机上打印调试信息的工具类

游戏发布到手机上调试的时候有时候会需要在屏幕上打印一些信息,我写了一个小工具类,分享出来,用的是OnGUI,很简单,直接上代码了 using UnityEngine; using System.Collections; using System.Collections.Generic; public class OnGUIDebug : MonoBehaviour { public static OnGUIDebug Instance; public int FontSize = 40; pub

发送邮箱验证信息的工具类

package cn.itcast.travel.util; import javax.mail.*;import javax.mail.internet.InternetAddress;import javax.mail.internet.MimeMessage;import java.util.Properties; /** * 发邮件工具类 */public final class MailUtils { private static final String USER = "[email