iOS崩溃前日志记录实现

如何使用Signal



因为错误抛出Signal,必须要专门做Signal处理。

在计算机科学中,信号(英语:Signals)是Unix、类Unix以及其他POSIX兼容的操作系统中进程间通讯的一种有限制的方式。它是一种异步的通知机制,用来提醒进程一个事件已经发生。当一个信号发送给一个进程,操作系统中断了进程正常的控制流程,此时,任何非原子操作都将被中断。如果进程定义了信号的处理函数,那么它将被执行,否则就执行默认的处理函数。

在项目工程中,要使用

#include <sys/signal.h>

sys/signal 文件内定义了大量的系统信号标识,信号处理函数可以通过 signal() 系统调用来设置。如果没有为一个信号设置对应的处理函数,就会使用默认的处理函数;否则信号就被进程截获并调用相应的处理函数。在没有处理函数的情况下,程序可以指定两种行为:忽略这个信号 SIG_IGN 或者用默认的处理函数 SIG_DFL 。

但是有两个信号是无法被截获并处理的: SIGKILL、SIGSTOP 。

//定义一个接收到信号的回调函数
void HandleException(int signo)
{
    printf("Lanou‘s sig is:%d",signo);
}
//注册Alerm信号的回调函数
signal(SIGALRM, HandleException);

Signal信号的类型


  • SIGABRT--程序中止命令中止信号
  • SIGALRM--程序超时信号
  • SIGFPE--程序浮点异常信号
  • SIGILL--程序非法指令信号
  • SIGHUP--程序终端中止信号
  • SIGINT--程序键盘中断信号
  • SIGKILL--程序结束接收中止信号
  • SIGTERM--程序kill中止信号
  • SIGSTOP--程序键盘中止信号 
  • SIGSEGV--程序无效内存中止信号
  • SIGBUS--程序内存字节未对齐中止信号
  • SIGPIPE--程序Socket发送失败中止信号

Signal信号在iOS开发中的使用方法



创建一个SignalHandler静态类

#import <Foundation/Foundation.h>
#include <sys/signal.h>
 
@interface SignalHandler : NSObject
// 静态方法注册signal处理函数
+ (void)RegisterSignalHandler;
@end

SignalHandler.mm

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

//当前处理的异常个数
volatile int32_t UncaughtExceptionCount = 0;
//最大能够处理的异常个数
volatile int32_t UncaughtExceptionMaximum = 10;
 
//捕获信号后的回调函数
void HandleException(int signo) {
    int32_t exceptionCount = OSAtomicIncrement32(&UncaughtExceptionCount);
    // 不处理超过10个异常
    if (exceptionCount > UncaughtExceptionMaximum) {
        return;
    }
    NSMutableDictionary *userInfo =[NSMutableDictionary dictionaryWithObject:[NSNumber numberWithInt:signo] forKey:@"signal"];
     
    //创建一个OC异常对象
    NSException *ex = [NSException exceptionWithName:@"SignalExceptionName" reason:[NSString stringWithFormat:@"Signal %d was raised.\n",signo] userInfo:userInfo];
     
    //获得单例SignalHandler并在阻塞主线程处理ex异常,因为本次处理设计UI
    [[SignalHandler Instance] performSelectorOnMainThread:@selector(HandleException:) withObject:ex waitUntilDone:YES];
}
 
@implementation SignalHandler
{
BOOL isDismissed = NO;
static  SignalHandler *s_SignalHandler =  nil;
}
+ (instancetype)Instance{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        if (s_SignalHandler == nil) {
            s_SignalHandler  =  [[SignalHandler alloc] init];
        }
    });
    return s_SignalHandler;
}
 
+ (void)RegisterSignalHandler {
    //注册程序由于abort()函数调用发生的程序中止信号
    signal(SIGABRT, HandleException);
    //注册程序由于非法指令产生的程序中止信号
    signal(SIGILL, HandleException);
    //注册程序由于无效内存的引用导致的程序中止信号
    signal(SIGSEGV, HandleException);
    //注册程序由于浮点数异常导致的程序中止信号
    signal(SIGFPE, HandleException);
    //注册程序由于内存地址未对齐导致的程序中止信号
    signal(SIGBUS, HandleException);
    //程序通过端口发送消息失败导致的程序中止信号
    signal(SIGPIPE, HandleException);
}

//处理异常用到的方法,在这里记录与处理崩溃
- (void)HandleException:(NSException *)exception {
    CFRunLoopRef runLoop = CFRunLoopGetCurrent();
    CFArrayRef allModes = CFRunLoopCopyAllModes(runLoop);
     
    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:exception.description message:@"点击按钮结束程序" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:nil];
    [alertView show];
 
    //当接收到异常处理消息时,让程序开始runloop,防止程序死亡直到isDimissed = YES
    while (!isDismissed) {
        for (NSString *mode in (NSArray *)allModes) {
            CFRunLoopRunInMode((CFStringRef)mode, 0.001, false);
        }
    }
    //恢复各信号的默认处理函数SIG_DFL
    CFRelease(allModes);
    NSSetUncaughtExceptionHandler(NULL);
    signal(SIGABRT, SIG_DFL);
    signal(SIGILL, SIG_DFL);
    signal(SIGSEGV, SIG_DFL);
    signal(SIGFPE, SIG_DFL);
    signal(SIGBUS, SIG_DFL);
    signal(SIGPIPE, SIG_DFL);
}
 
- (void)alertView:(UIAlertView *)anAlertView clickedButtonAtIndex:(NSInteger)anIndex {
    isDismissed = YES;
}
@end
时间: 2024-08-04 13:22:27

iOS崩溃前日志记录实现的相关文章

IOS日志记录

日志 在开发过程中,众所周知,日志记录调试的关键部分,尤其是当产品发布的时候,有用户feedback一些崩溃问题或者是其他问题时,日志就显得尤其重要,通过分析日志可以很快地找出问题的症结所在并快速解决问题. 恰当的记录用户日志是一门艺术.什么样的信息应该写入日志(通常包括用户行为和错误信息,分开记录),写入日志的信息太少不利于调试,而频繁地记录日志则会影响系统的性能,还会使得日志文件迅速膨胀导致难以查找到需要的信息.对于不同的应用,应该记录的信息是不用的,不过还是有一些通用的规则的.关于日志引擎

Linux下定时切割Mongodb数据库日志并删除指定天数前的日志记录(转)

文章转自:http://www.osyunwei.com/archives/8998.html 说明: 操作系统:CentOS Mongodb安装目录:/usr/local/mongodb Mongodb数据库存放目录:/home/data/mongodb/mongodb_data Mongodb日志存放目录:/home/data/mongodb/mongodb_log 实现目的: 对Mongodb数据库日志按天保存,并且只保留最近7天的日志记录. 具体操作: 使用Mongodb数据库自带的命令

IOS崩溃日志解析(crash log)

IOS的应用程序少不了crash,互联网统计分析工具友盟有一项目错误分析的功能,专门用于应用程序崩溃日志统计,最近研究友盟上统计到的崩溃日志,在此对崩溃日志做一个简单的总结. IOS崩溃日志分类: 一.低内存崩溃:IOS设备检测到低内存时,虚拟内存系统发出通知请求应用释放内存.这些通知发送到所有正在运行的应用和进程,试图收回一些内存.如果内存使用依然居高不下,系统将会终止后台线程以缓解内存压力.如果可用内存足够,应用将能够继续运行而不会产生崩溃报告.否则,应用将被iOS终止,并产生低内存崩溃报告

iOS崩溃日志

今天看crash report ,有这样两个crash: 调用 stopUpdatingLocation 函数的是一个CLLocationManager 类型的对象,为什么报错的时候会把这个对象转成NSConcerteAttributedString类型? 调用getEsubmissionResult方法的是一个UIViewController类型的对象,为什么会转成_NSCFString类型? iOS崩溃日志 >> ios 这个答案描述的挺清楚的:http://www.goodpm.net/

ios 崩溃日志揭秘

http://www.raywenderlich.com/zh-hans/30818/ios%E5%BA%94%E7%94%A8%E5%B4%A9%E6%BA%83%E6%97%A5%E5%BF%97%E6%8F%AD%E7%A7%98 0x8badf00d: 读做 "ate bad food"! (把数字换成字母,是不是很像 :p)该编码表示应用是因为发生watchdog超时而被iOS终止的.  通常是应用花费太多时间而无法启动.终止或响应用系统事件. 0xbad22222: 该编码

常用获取Android崩溃日志和IOS崩溃日志的几种方法

一:前言 在日常测试app时,经常会遇到崩溃问题,测试快速抓取到崩溃日志可以有效方便开发进行定位,快速解决问题所在测试做到测试分析,定位是非常重要的,这也是判断一个测试能力指标的一大维度. 二:Android崩溃日志 一.通过adb logcat获取 # 清除日志,新手上路时,日志内容很多,对于能毕现的日志,可以先清除后重新获取 adb logcat -c # 然后再次运行崩溃操作,再抓取日志 # 存储日志到当前目录下的 carsh.log 中 adb logcat -d *:W > crash

IOS异常日志记录与展现功能

在平常的APP开发过程中经常碰到程序遇到异常闪退的问题,通过日志可以把相关的详细错误信息进行记录,本实例要记录不管在哪个页面出错都要进行记录,这边使用到的日志记录插件CocoaLumberjack,以文本的形式记录错误信息,然后再去读取各个文本的内容进行展示:当然现在有很多第三方的插件比如友盟也已经集成错误记录的功能: 效果图如下: 1:封装DDLogger的类 MyFileLogger.h文件 #import <Foundation/Foundation.h> #import <Coc

IOS异常日志记录与展现

在平常的APP开发过程中经常碰到程序遇到异常闪退的问题,通过日志可以把相关的详细错误信息进行记录,本实例要记录不管在哪个页面出错都要进行记录,这边使用到的日志记录插件CocoaLumberjack,以文本的形式记录错误信息,然后再去读取各个文本的内容进行展示:当然现在有很多第三方的插件比如友盟也已经集成错误记录的功能: 效果图如下: 1:封装DDLogger的类 MyFileLogger.h文件 #import <Foundation/Foundation.h> #import <Coc

Linux下定时切割nginx日志并删除指定天数前的日志记录

nginx的log日志分为access.log和error.log:其中access.log 记录了哪些用户.哪些页面以及用户浏览器.ip和其他的访问信息:error.log则是记录服务器错误日志. error.log日志的形式如下: 201.158.69.116 - - [03/Jan/2013:21:17:20 -0600] fwf[-] tip[-] 127.0.0.1:9000 0.007 0.007 MX pythontab.com GET /html/test.html HTTP/1