iOS_调试技巧详解

2018-08-29  本文已影响40人  Lin__Chuan

上次介绍了一下LLDB的使用, 但实际上在解决一些问题的时候, 并不是直接使用LLDB调试指令的, 会通过各种工具或技巧来解决问题, 本篇文章就是来探讨一些相关的方法.

1. signal SIGABRT

image.png

这在OC中经常出现, 一般情况下, 数组越界或者调用的方法不存在, 会触发这个错误
解决方法:

image.png
(lldb) image lookup --address 0x00000001087418c3
      Address: LCCustomTools_OC[0x000000010000f8c3] (LCCustomTools_OC.__TEXT.__text + 59507)
      Summary: LCCustomTools_OC`-[AppDelegate application:didFinishLaunchingWithOptions:] + 195 at AppDelegate.m:29

以上这两种问题, 在Swift中又不一样, 编译器会直接提示代码错误.


数组越界.png 无法调用方法.png

那么这个signal SIGABRT到底是什么呢?

这里展示了所有的Unix信号


image.png
在以上列出的信号中,程序不可捕获、阻塞或忽略的信号有:SIGKILL,SIGSTOP
不能恢复至默认动作的信号有:SIGILL,SIGTRAP
默认会导致进程流产的信号有:SIGABRT,SIGBUS,SIGFPE,SIGILL,SIGIOT,SIGQUIT,SIGSEGV,SIGTRAP,SIGXCPU,SIGXFSZ
默认会导致进程退出的信号有:SIGALRM,SIGHUP,SIGINT,SIGKILL,SIGPIPE,SIGPOLL,SIGPROF,SIGSYS,SIGTERM,SIGUSR1,SIGUSR2,SIGVTALRM
默认会导致进程停止的信号有:SIGSTOP,SIGTSTP,SIGTTIN,SIGTTOU
默认进程忽略的信号有:SIGCHLD,SIGPWR,SIGURG,SIGWINCH

2. EXC_BAD_ACCESS(Zombie Objects)

EXC_BAD_ACCESS,指向某块内存发送消息,但是该内存无法响应对应的消息指令。比如, 向一个已经释放的对象发送消息, 就会报此错误.
在MRC环境下, 测试以下代码,

image.png

因为对象arr已经被释放, 所以再次调用arrobjectAtIndex:方法,就会报EXC_BAD_ACCESS, 也叫坏内存访问, 为了精确定位到到底是哪里的坏内存被访问了, 在Product -> Scheme -> Edict Scheme中, 勾选Zombie Objects

image.png
再此运行代码, 就能发现具体出错位置. image.png

3. Address Sanitizer

但是如果是在 malloc 对象方面, Zombie Objects就很难起作用了. 比如下面这种, 明显90已经超出了原来的内存分配范围, 仍然去赋值, 程序会马上退出

image.png

还是在原来的界面, 勾选Address Sanitizer, 再次运行, 就能发现问题所在

Address Sanitizer 设置.png

报堆内存溢出


出错信息.png

Address Sanitizer 就已经支持的错误检查包括:

4. Memory Leak (内存泄露)

当希望某个对象释放掉的时候,它没有按照预想被释放掉,导致不必要的内存占用, 比较常见的是Retain Circle(循环引用).

在Teacher.m里
-(void)teach:(void (^)())block
{
    self.caseBlock = block;  
    if (self.caseBlock) {
        self.caseBlock();
    }
}

在TeacherVC.m里
[self.teacher teach:^ {
    self.name = @"jack";
}];

// dealloc
- (void)dealloc
{
    NSLog(@"==== dealloc ====");
}

self -> teacher -> block -> self

解决方法:

__weak typeof(self) weakSelf = self;
[self.teacher teach:^{
    typeof(weakSelf) strongSelf = weakSelf;
    strongSelf.name = @"jack";
}];

self -> teacher -> block -> strongSelf -> weakSelf

instruments里面看到的现象是这样的, 可以很明显看到是在调用teach方法里面泄露的, 可以在Xcode -> Open Developer Tool -> Instrument, 打开Instrument

image.png

参考
Unix中的信号
ARC下用块(block)的循环引用问题样例探究
调试技巧: 内存

上一篇 下一篇

猜你喜欢

热点阅读