必赢亚洲手机app下载


766net必赢亚洲手机版五个总结机必备的小神器

技巧长期来看被高估

xcode 下crash处理

用作一名开发者,修改bug是一件不可幸免的作业,没有稳定的技艺,就从未永远坚挺的代码,唯有不断的上学改变。
先领悟下crash:
crash一般就二种状态:signal(中断,信号量) 和EXC_BAD_ACCESS(异常)

signal分类

查阅iOS SDK中断信号有好多…

signal.png

上面介绍下,实际开发中相见频率较高的多少个:
SIGSEGV**** (Segmentation fault)
访问了未曾权力的内部存款和储蓄器地址(系统内部存款和储蓄器地址等)
766net必赢亚洲手机版,SIGBUS**** (Bus error)
访问了不算的内部存款和储蓄器地址
SIGFPE**** (Floating point exception)
浮点数运算很是
SIGPIPE
次第Socket发送退步中止信号
SIGILL
私行命令
SIGTRAP
由断点指令或其余trap指令发生. 由debugger使用
SIGABRT
次第中止命令中止信号

EXC_BAD_ACCESS 是我们付出进度中最普遍的,简单的讲:就是造访了不在的地点值

对我们开发者来说能出现必现的crash是美满的,因为能够连接Xcode调式,查看crash的库房音讯。
先是步:打开那一个断点,打开这几个能找到一般大约的crash点

荧屏快速照相 二零一六-12-16 下午8.57.05.png

第③步:点击Product->艾德it Scheme,在Run->Diagnostics 打开Zombie
Objects(僵尸对象) 选项。针对exc_bad_access
类的crash点是相比较好的化解办法。如下图:

图1

诚如crash会定位到

*** -[__NSArrayM release]: message sent to deallocated 
*** -[ChatViewController respondToSelector]: message sent to deallocated instance

本来xcode7今后多了个 Address Sanitizer,打开这一个也是足以的。

crash原因
基本都可以用上述措施定位到了。假如那一个输出是地点值,大家得以在Xcode
输出控制台输入命令行:po 0x1000e6000 能够查阅到实际的类名

对此不可重现的crash,大家只可以通过其余艺术。

1.对crash日志文件符号化。

诚如大家用爆发过crash的无绳电话机连接电脑,通过xcode->window->Devices
选中大家的无绳电话机 view Device logs,导入crash日志,
在得到对应App的 .ipa 和.dsym文件,多个位于电脑一样文件,
在相应crash文件右键选拔Re-Symbolicate
Log,之后能收看原先是我们app内的地点已经变为代码明文.

如何获得.dsym文件?
装进在Archive的时候会生成.xcarchive文件,然后右键展现包内容就足以观望.dsYM文件和.app文件,一般那些不会删除.xcarchive的。

操作如下图:

符号化操作

假定您是在一些第贰方平台(如友盟)上收看crash,大概是crash日志中的爆发crash的线程,那时候,你大概就要求自身去符号化对应的类
选拔形式如下:

atos -arch <Binary Architecture> -o <Path to dSYM file>/Contents/Resources/DWARF/<binary image name> -l <load address> <address to symbolicate>

tn2151_find_uuid.png

地点的UUID 是指.dsym文件对应的
详细分析参考官方文书档案:https://developer.apple.com/library/content/technotes/tn2151/\_index.html\#//apple\_ref/doc/uid/DTS40008184-CH1-SYMBOLICATION

2.捕获特别日志输出

在代码中添加捕获相当代码,将捕获到的日记打印出来,存入到文书档案,并在方便的年月反馈服务器。Flurry,友盟等第二方应该是看似方法达成的。
上边贴一下代码吧。这么些代码也是很早从前网上copy过来的,网上应该也能找到。

#include <libkern/OSAtomic.h>
#include <execinfo.h>

// 系统信号截获处理方法
void signalHandler(int signal);
// 异常截获处理方法
void exceptionHandler(NSException *exception);

const int32_t _uncaughtExceptionMaximum = 10;

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];
    // 现在就可以上报信息到服务器
}

@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

总结
在实际上支出中要留意以下:
① 、幸免数组越界 当调用objectAtIndex时只顾是或不是越界
② 、指针空的论断,那种crash也是相比常见的,在走访对象此前一要要保管指标存在。
③ 、NSNotification、Delegate和NSTimer移除,通知、代理和定时器等在应用后自然要记得释放,或最终在dealloc函数中置nil/removeObserve/invalidate
否者很简单发生crash。
NSTimer也足以重复改造一下运用,可参看很久前封装的类https://github.com/weskhen/WeakTimer
④ 、在跨类调用方法时,或访问API对系统版本有供给时,最佳使用respondsToSelector
判断访问,尤其是delegate代理使用。
伍 、内部存款和储蓄器管理,在接收内部存储器警告一定要立马放出东西,因为不做处理,很简单被系统杀掉。
陆 、八线程并发操作引发的crash,在多并发环境中,假诺3个线程已经将数据删除,别的二个线程去拜访,因数额不设有一定会crash,所以毫无疑问要透过加锁机制来消除难点,在初学CoreData数据库时日常遇上过。

参照地址:
http://blog.csdn.net/arthurchenjs/article/details/7049175

相关文章

No Comments, Be The First!
近期评论
    功能
    网站地图xml地图