100steps/Blogs

测试-内存泄露

WENKI opened this issue · 10 comments

WENKI commented

波板糖一直出现的白盒测试的问题,过程中有很多想法

WENKI commented

讲讲道理,以前我也一直觉得使用了arc就不用理会泄露问题,后来发现反而因为arc会出现一些泄露,很多时候仍旧需要手动释放。
eg.一个对象存入到集合中的时候,默认会保存它的强指针,如果最后不对这个集合进行清空操作,一样会有内存溢出的情况。
Person * p = [[Person alloc] init];
NSMutableArray * arr = [[NSMutableArray alloc] init];
[arr addObject:p];
把对象从集合中移除的时候,也会释放掉这个对象的强指针
[arr removeObject:p];
或者[arr removeAllObjects];
而接下来才是重点:
arr = nil;//如果不进行赋值为nil的操作,一样存在内存溢出的现象,赋值为nil系统会对其进行清空所有强指针的操作.
p = nil;

WENKI commented

delegate声明为strong的时候常常出现的参照无能的情况也是如此。
两个强指针出现溢出是arc搞定不了的
当然,如果只是这样的泄露 改一下属性之类的也可以搞定。一个对象尚未被释放,但是不再被引用的了,我称之为真的泄露了。
但是还有一种泄露,是内存增长型,无限内存增长型,比如波板糖。我在点击时引发的事件流会导致一定的泄露,然后二次点击时成倍增长,直到大到被看门狗kill掉。内存增长有很多情况,不一定就是代码,也可能是框架或者其他。
heap shot分析可以测试出这个问题,但是讲道理,它检测不出具体的代码,只能检测出某个动作导致的泄露,然后warning。通过选择HardwareSimulate内存警告在iOS模拟器的菜单栏模拟内存警告。你会发现,记忆体使用量出现小幅回落,但绝对不会回到最初。

WENKI commented

Xcode中Instruments的使用只能在这里给你一个提示,问题出在哪里,它不能告诉你确切位置的泄漏。
即使我们测试出专线二刷新时会有大幅度的泄露,改起来也仍然很难。我们使用时app出现的卡顿,闪退等现象,通过手动释放内存可以得到一定的优化。我一直觉得测试是一件很重要的事情,尤其是白盒,有条件的话其实每个项目上线前都应该做测试优化

非iOS表示看得感觉没头没尾的像火星文一样_(:зゝ∠)_

虽然我看不懂,但还是建议要利用 markdown 语法排一下版。。

WENKI commented

很抱歉。。我在家没有整理就发了
之后会改进和更新

只要[arr removeObject:p];后就不会保留任何其他对象的强指针了吧。。
就算不arr=nil,最多也只是泄漏了一个空数组的内存?

另外,直接设arr=nil 可以吗。。

感觉ARC和Python的内存回收机制很类似啊
Python中的变量其实就是指向对象的指针,当指针之间赋值时,会改变对象的引用计数

def bar(): 
    a = Foo() # a指向新建的Foo对象X,X引用计数为1
    b = Foo() # b指向新建的Foo对象Y,Y引用计数为1
    a = b       # 使a指针指向对象Y,对象X引用计数减1,为0,被销毁;对象Y引用计数加1,变为2
    a = None # a解除对对象Y的引用,对象Y引用计数减1,变为1
    # b变量退出作用域,其指向对象Y引用计数减1,被销毁

Python好像还附带了标记清除回收的机制,解决循环引用导致的内存泄露。

----------------------------我是分割线-----------------------------

arr会发生泄露应该是产生循环引用了,把arr置为nil破坏了循环,使arr可以被回收。
没有发生循环引用的arr,不置为nil也是可以正常回收的。

巧用函数的域可以让语言帮你回收内存