快速构建网站,网站建设的实施制作阶段包括,鹤壁做网站的公司,怎么设计一个网站文章目录 1.Crash 捕获1.2.NSException1.2.C异常1.3.Mach异常1.4.Unix 信号 2.Crash 防护2.1.方法未实现2.2.KVC 导致 crash2.3.KVO 导致 crash2.4.集合类导致 crash2.5.其他需要注意场景#xff1a; 1.Crash 捕获
根据 Crash 的不同来源#xff0c;分为以下三类#xff1a… 文章目录 1.Crash 捕获1.2.NSException1.2.C异常1.3.Mach异常1.4.Unix 信号 2.Crash 防护2.1.方法未实现2.2.KVC 导致 crash2.3.KVO 导致 crash2.4.集合类导致 crash2.5.其他需要注意场景 1.Crash 捕获
根据 Crash 的不同来源分为以下三类
1.2.NSException
应用层的异常未被捕获的异常导致程序向自身发送了 SIGABRT 信号而崩溃是应用程序自己可控的。对于未被捕获的异常是可以通过 try-catch 或 NSSetUncaughtExceptionHandler() 机制类捕获的。
常见的 Exception
NSInvalidArgumentException非法参数异常。加强对参数的检查避免传入非法参数特别是标记为 nonull 的参数。NSRangeException越界异常NSGenericException遍历的同时对原集合进行修改NSInternalInconsistencyException不一致异常。如 NSDictionary 当 NSMutableNSDictionary 使用。NSFileHandleOperationException文件处理异常。常见的是存储空间不足NSMallocException内存异常。如内存不足。 系统定义的所有 Exception 见 NSExceptionName
捕获 NSExpection
// 记录之前的Crash回调函数如果有的话
static NSUncaughtExceptionHandler *previousUncaughtExceptionHandler NULL; (void)registerUncaughtExceptionHandler {// 将别人之前注册的Crash回调取出并备份previousUncaughtExceptionHandler NSGetUncaughtExceptionHandler();// 然后再注册自己的NSSetUncaughtExceptionHandler(UncaughtExceptionHandler);
}// 崩溃时的回调函数
static void UncaughtExceptionHandler(NSException * exception) {// 异常的堆栈信息NSArray *stackInfo [exception callStackSymbols];// 出现异常的原因NSString *reason [exception reason];// 异常名称NSString *name [exception name];// 异常错误报告NSString *exceptionInfo [NSString stringWithFormat:uncaughtException异常错误报告:\n name:%\n reason:\n %\n callStackSymbols:\n %, name, reason, [stackInfo componentsJoinedByString:\n]];// 保存Crash日志到沙盒cache目录[SKTool cacheCrashLog:exceptionInfo name:CrashLog(UncaughtException)];// 在自己handler处理完后记得把别人的handler注册回去形成规范的SOPif (previousUncaughtExceptionHandler) {previousUncaughtExceptionHandler(exception);}// 杀掉程序这样可以防止同时抛出的SIGABRT被Signal异常捕获kill(getpid(), SIGKILL);
}1.2.C异常
系统捕获到 C 异常后会将其转换为 OC 异常抛出此时的调用堆栈是在异常发生时的队长但若转换失败则会调用 __cxa_throw 抛出异常此时的调用队长是处理异常的堆栈导致原始异常调用堆栈丢失。 捕获 C 异常
设置异常处理函数
g_originalTerminateHandler std::set_terminate(CPPExceptionTerminate);调用 set_terminate(CPPExceptionTerminate) 设置新的全局终止处理函数并保持旧的函数。
重写 __cxa_throw
void __cxa_throw(void* thrown_exception, std::type_info* tinfo, void (*dest)(void*)) {// 获取调用堆栈并存储// 再调用原始的 __cxa_throw 函数
}异常处理函数 __cxa_throw 往后执行进入 set_terminate 设置的异常梳理函数。判断如果是 OC 异常则什么也不多让 OC 异常机制处理否则获取异常信息。 1.3.Mach异常
内核层的异常。用户态开发者可以通过 Mach API 设置 thread、task、hot 的异常端口来捕获 Mach 异常。
tasks资源所有权单位。每个任务由一个虚拟地址空间、一个端口权限名称控件、一个或多个线程组成。类似于进程threads任务中 CPU 执行的单位ports安全的单工通信通道只能通过发生和接收功能进行访问。
与 Mach 异常相关的 API 有
task_get_exception_ports获取 task 的异常端口task_set_exception_ports设置 task 的异常端口mach_port_allocate创建调用者指定的端口权限类型mach_port_insert_right将指定的端口插入目标 task
注意避免在 Xcode 联调时监听会死锁。 1.4.Unix 信号
又称 BSD 信号如果开发者没有捕获 Mach 异常则会被 host 层的方法 ux_exception() 将异常转换为对应的 Unix 信号并通过方法 threadsignal() 将信号投递到出错线程。可以同 signal(x, SignalHandler) 来捕获 signal。
信号表
SIGHUP挂起SIGINT程序终止信号 interrupt在用户键入 INTR 字符通常是 Ctrl-C是发出用于通知前台进程组终止进程。SIGQUIT程序退出信号 quit由 QUIT 字符来控制通常是Ctrl-程序在收到该信号退出时会生成 core 文件。SIGILL执行非法指令SIGTRAP由断点指令或陷阱指令SIGABRT程序打断信号 abort。SIGBUS非法地址SIGFPE致命的算术运算错误SIGKILL立即结束程序的运行。不能被阻塞、处理和忽略。SIGUSR1用户信号1SIGSEGV无效内存访问SIGUSR2用户信号2SIGPIPE管道破裂。进程间的通信如管道的异常读写。SIGALRMalarm 发出的信号SIGTERM终止信号可被阻塞和处理。通常用来要求程序自己正常退出SIGSTKFLT栈溢出SIGCHLD子进程退出SIGCONT进程继续SIGSTOP进程停止SIGTSTP进程停止SIGTTIN进程停止后台进程从终端读数据时SIGTTOU进程停止后台进程想终端写数据时SIGURGI/O有紧急数据达到当前进程SIGXCPU进程的CPU时间篇到期SIGXFSZ文件大小超出上限SIGVTALRM虚拟时钟超时SIGPROFprofile 时钟超时SIGWINVH窗口大小改变SIGIOI/O相关SIGPWR关机SIGSYS非法的系统调用 Tips: 在终端输入 kill -l 查看所有的 signal 信号。 捕获信号
// 一般需要捕获的信号
static const int g_fatalSignals[] {SIGABRT,SIGBUS,SIGFPE,SIGILL,SIGPIPE,SIGSEGV,SIGSYS,SIGTRAP,
};
void installSignalHandler() {stack_t ss;struct sigaction sa;struct timespec req, rem;long ret;// 申请一块内存空间作为可选的信号处理函数栈使用ss.ss_flags 0;ss.ss_size SIGSTKSZ;ss.ss_sp malloc(ss.ss_size);// 使用 sigaltstack 函数通知系统可选的信号处理栈帧的存在及其位置sigaltstack(ss, NULL);// 指定 SA_ONSTACK 标志通知系统这个信号处理函数应该在可选的栈帧上面执行注册的信号处理函数memset(sa, 0, sizeof(sa));sa.sa_handler handleSignalException;sa.sa_flags SA_ONSTACK;sigaction(SIGABRT, sa, NULL);
}void XXXHandleSignalException(int signal) {// 打印堆栈NSMutableString *crashInfo [[NSMutableString alloc] init];[crashInfo appendString:[NSString stringWithFormat:signal:%d\n,signal]];[crashInfo appendString:Stack:\n];void* callstack[128];int i, frames backtrace(callstack, 128);char** strs backtrace_symbols(callstack, frames);for (i 0; i frames; i) {[crashInfo appendFormat:%s\n, strs[I]];}NSLog(%, crashInfo);// 移除其他 Crash 监听, 防止死锁NSSetUncaughtExceptionHandler(NULL);signal(SIGHUP, SIG_DFL);signal(SIGINT, SIG_DFL);signal(SIGQUIT, SIG_DFL);signal(SIGABRT, SIG_DFL);signal(SIGILL, SIG_DFL);signal(SIGSEGV, SIG_DFL);signal(SIGFPE, SIG_DFL);signal(SIGBUS, SIG_DFL);signal(SIGPIPE, SIG_DFL);
}2.Crash 防护
2.1.方法未实现
找不到方法的实现unrecognized selector sent to instance查找过程详情可见iOS_Objective-C 消息发送消息查找 及 消息转发过程
解决方案 给 NSObject 新增分类实现消息转发的几个方法来规避 Crash
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {if ([self respondsToSelector:aSelector]) { // 已实现不做处理return [self methodSignatureForSelector:aSelector];}return [NSMethodSignature signatureWithObjCTypes:v:];
}
- (void)forwardInvocation:(NSInvocation *)anInvocation {NSLog(% cant responds %, NSStringFromClass([self class]), NSStringFromSelector(anInvocation.selector));
}(NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {if ([self respondsToSelector:aSelector]) { // 已实现不做处理return [self methodSignatureForSelector:aSelector];}return [NSMethodSignature signatureWithObjCTypes:v:];
}(void)forwardInvocation:(NSInvocation *)anInvocation {NSLog(% cant responds %, NSStringFromClass([self class]), NSStringFromSelector(anInvocation.selector));
}2.2.KVC 导致 crash
KVC 的搜索模式详情可见iOS_KVCKey-Value Coding-2访问者搜索模式当最终找不到对应的key时会导致 crash。
常见场景
场景1key 不存在
XXXClass * obj [[XXXClass alloc] init];
[obj setValue:nil forKey:xxx];
// reason: [XXXClass 0x2810bfa80 setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key xxx.id value [obj valueForKey:xxx];
// Thread 1: [MOPerson 0x600000c76c10 valueForUndefinedKey:]: this class is not key value coding-compliant for the key xxx.场景2key 为 nil
XXXClass* obj [[XXXClass alloc] init];
[obj setValue:value forKey:nil];
// reason: *** -[XXXClass setValue:forKey:]: attempt to set a value for a nil key// 另外value 为 nil 不会崩溃
[obj setValue:nil forKey:name];解决方案覆写系统会抛出异常的实现
- (id)valueForUndefinedKey:(NSString *)key {NSLog(Error: valueForUndefinedKey: %, key);return nil;
}
- (void)setValue:(id)value forUndefinedKey:(NSString *)key {NSLog(Error: setValue:% forUndefinedKey: %, value, key);
}2.3.KVO 导致 crash
场景
观察者/被观察者 是局部变量未实现 observeValueForKeyPath:ofObject:changecontext:移除未注册的观察者如重复移除 Tips: 重复添加观察者不会crash但会回调多次 解决方案
addObserver 和 removeObserver 必须成对出现使用 Facebook 的 KVOController 实现 2.4.集合类导致 crash
常见场景
越界
NSArray *arr [NSArray array];
id value [arr objectAtIndex:1];
// Thread 1: *** -[__NSArray0 objectAtIndex:]: index 1 beyond bounds for empty array塞入 nil
NSMutableArray *arr [NSMutableArray array];
[arr addObject:nil];
// Thread 1: *** -[__NSArrayM insertObject:atIndex:]: object cannot be nilNSMutableDictionary *dict [NSMutableDictionary dictionary];
[dict setObject:nil forKey:xxx];
// Thread 1: *** -[__NSDictionaryM setObject:forKey:]: object cannot be nil (key: xxx)解决方案
使用 runtime 在这些修改方法调用前添加判空处理详情见Demo 2.5.其他需要注意场景
performSelector: 必须先判断 respondsToSelector:调用 delegate 的方法前必须先判断 respondsToSelector:id 类型不能强转必须先判断 isKindOfClass:访问 UIKit 时一定要 dispatch 到 main queue一个实例不能保证线程访问安全时记得要加读写锁dispatch_group_leave 比 dispatch_group_enter 必须成对出现检查属性的修饰方式 (assign/strong/weak/copy)block 调用前必须判空遍历结合类型对象时不要同时对其进行修改耗时操作一定 dispatch 到子线程避免触发 watchDogDebug 模式开启僵尸模式方便即时发现问题。使用 Xcode 的 Address Sanitizer 检测地址访问越界 参考 iOS Crash/崩溃/异常 捕获 Linux 信号列表 浅谈 iOS 中的 Crash 捕获与防护 iOS中常见Crash总结 文章转载自: http://www.morning.gsqw.cn.gov.cn.gsqw.cn http://www.morning.lynb.cn.gov.cn.lynb.cn http://www.morning.qbtj.cn.gov.cn.qbtj.cn http://www.morning.mkydt.cn.gov.cn.mkydt.cn http://www.morning.rjfr.cn.gov.cn.rjfr.cn http://www.morning.kpxnz.cn.gov.cn.kpxnz.cn http://www.morning.qpmwb.cn.gov.cn.qpmwb.cn http://www.morning.ktnmg.cn.gov.cn.ktnmg.cn http://www.morning.cnvlog.cn.gov.cn.cnvlog.cn http://www.morning.tbstj.cn.gov.cn.tbstj.cn http://www.morning.lgznc.cn.gov.cn.lgznc.cn http://www.morning.ypzsk.cn.gov.cn.ypzsk.cn http://www.morning.qlry.cn.gov.cn.qlry.cn http://www.morning.srckl.cn.gov.cn.srckl.cn http://www.morning.rntgy.cn.gov.cn.rntgy.cn http://www.morning.qxlgt.cn.gov.cn.qxlgt.cn http://www.morning.twmp.cn.gov.cn.twmp.cn http://www.morning.ckzjl.cn.gov.cn.ckzjl.cn http://www.morning.xqjh.cn.gov.cn.xqjh.cn http://www.morning.wdprz.cn.gov.cn.wdprz.cn http://www.morning.chehb.com.gov.cn.chehb.com http://www.morning.bqyb.cn.gov.cn.bqyb.cn http://www.morning.xqbgm.cn.gov.cn.xqbgm.cn http://www.morning.xrksf.cn.gov.cn.xrksf.cn http://www.morning.nzklw.cn.gov.cn.nzklw.cn http://www.morning.yppln.cn.gov.cn.yppln.cn http://www.morning.kryxk.cn.gov.cn.kryxk.cn http://www.morning.skkln.cn.gov.cn.skkln.cn http://www.morning.fbjnr.cn.gov.cn.fbjnr.cn http://www.morning.jbxmb.cn.gov.cn.jbxmb.cn http://www.morning.ydhck.cn.gov.cn.ydhck.cn http://www.morning.nnrqg.cn.gov.cn.nnrqg.cn http://www.morning.mjbnp.cn.gov.cn.mjbnp.cn http://www.morning.lmdfj.cn.gov.cn.lmdfj.cn http://www.morning.znqxt.cn.gov.cn.znqxt.cn http://www.morning.qgghr.cn.gov.cn.qgghr.cn http://www.morning.cfocyfa.cn.gov.cn.cfocyfa.cn http://www.morning.skbhl.cn.gov.cn.skbhl.cn http://www.morning.jmbfx.cn.gov.cn.jmbfx.cn http://www.morning.yqgbw.cn.gov.cn.yqgbw.cn http://www.morning.lcplz.cn.gov.cn.lcplz.cn http://www.morning.kjfqf.cn.gov.cn.kjfqf.cn http://www.morning.jqllx.cn.gov.cn.jqllx.cn http://www.morning.mszwg.cn.gov.cn.mszwg.cn http://www.morning.sjzsjsm.com.gov.cn.sjzsjsm.com http://www.morning.gwjqq.cn.gov.cn.gwjqq.cn http://www.morning.bnlsd.cn.gov.cn.bnlsd.cn http://www.morning.bwxph.cn.gov.cn.bwxph.cn http://www.morning.zhffz.cn.gov.cn.zhffz.cn http://www.morning.jfxth.cn.gov.cn.jfxth.cn http://www.morning.cgthq.cn.gov.cn.cgthq.cn http://www.morning.slfkt.cn.gov.cn.slfkt.cn http://www.morning.pjxw.cn.gov.cn.pjxw.cn http://www.morning.knsmh.cn.gov.cn.knsmh.cn http://www.morning.xmrmk.cn.gov.cn.xmrmk.cn http://www.morning.xwbwm.cn.gov.cn.xwbwm.cn http://www.morning.pgxjl.cn.gov.cn.pgxjl.cn http://www.morning.lqtwb.cn.gov.cn.lqtwb.cn http://www.morning.jtmql.cn.gov.cn.jtmql.cn http://www.morning.fwdln.cn.gov.cn.fwdln.cn http://www.morning.zkjqj.cn.gov.cn.zkjqj.cn http://www.morning.spdyl.cn.gov.cn.spdyl.cn http://www.morning.gmwdl.cn.gov.cn.gmwdl.cn http://www.morning.ndtmz.cn.gov.cn.ndtmz.cn http://www.morning.mqnbm.cn.gov.cn.mqnbm.cn http://www.morning.wztlr.cn.gov.cn.wztlr.cn http://www.morning.mkyny.cn.gov.cn.mkyny.cn http://www.morning.gbtty.cn.gov.cn.gbtty.cn http://www.morning.mcpby.cn.gov.cn.mcpby.cn http://www.morning.rgfx.cn.gov.cn.rgfx.cn http://www.morning.chtnr.cn.gov.cn.chtnr.cn http://www.morning.bxgpy.cn.gov.cn.bxgpy.cn http://www.morning.rrxmm.cn.gov.cn.rrxmm.cn http://www.morning.zmpqh.cn.gov.cn.zmpqh.cn http://www.morning.snxbf.cn.gov.cn.snxbf.cn http://www.morning.ccsdx.cn.gov.cn.ccsdx.cn http://www.morning.lkpzx.cn.gov.cn.lkpzx.cn http://www.morning.gynls.cn.gov.cn.gynls.cn http://www.morning.lqklf.cn.gov.cn.lqklf.cn http://www.morning.xrhst.cn.gov.cn.xrhst.cn