编译器并不会判断performSelector调用了什么方法,ARC不会添加释放方法(关键是也不知道采用何种释放手段)。
例如下面代码:
[NSObject alloc];
编译器在执行时,会添加objc_release方法来释放创建的NSObject对象,
-> 0x10ea80666 <+54>: mov rax, qword ptr [rip + 0x26bb] ; (void *)0x000000010fa2dea8: NSObject
0x10ea8066d <+61>: mov rsi, qword ptr [rip + 0x269c] ; "alloc"
0x10ea80674 <+68>: mov rdi, rax
0x10ea80677 <+71>: call 0x10ea80a18 ; symbol stub for: objc_msgSend
0x10ea8067c <+76>: mov rdi, rax
0x10ea8067f <+79>: call 0x10ea80a24 ; symbol stub for: objc_release
而采用performSelector执行时,
[NSObject performSelector:@selector(alloc)];
编译结果如下,可以看到在函数返回之前,编译器也没有加入任何释放NSObject对象的代码。而我们知道通过alloc创建的对象,需要通过objc_release来释放,所以会造成内存泄漏。
0x10f918666 <+54>: mov rax, qword ptr [rip + 0x26c3] ; (void *)0x00000001108c5ea8: NSObject
0x10f91866d <+61>: mov rdx, qword ptr [rip + 0x269c] ; "alloc"
0x10f918674 <+68>: mov rsi, qword ptr [rip + 0x269d] ; "performSelector:"
0x10f91867b <+75>: mov rdi, rax
0x10f91867e <+78>: call 0x10f918a18 ; symbol stub for: objc_msgSend
-> 0x10f918683 <+83>: mov qword ptr [rbp - 0x28], rax
0x10f918687 <+87>: add rsp, 0x30
0x10f91868b <+91>: pop rbp
0x10f91868c <+92>: ret
在这种情况下,继续执行,然后打开memory graph查看内存:
内存泄漏查看
果然发现了内存泄漏。
网友评论