ios 内存小结
来源:互联网 发布:通达信股票行情软件 编辑:程序博客网 时间:2024/05/18 00:44
转自:http://blog.csdn.net/x6587305x/article/details/46802447
这是 看 书籍 Objective-C 高级编程 ios与os x多线程和内存管理 一书的随记。
1 arc
首先记录一下几个调试的东西
调试
1.查看 autoreleasePool 池里面的对象
extern void _objc_autoreleasePoolPrint();
_objc_autoreleasePoolPrint();
---------------上面的这个私有函数本人在IOS调用一直没有输出,mac怎有。。。----------是哪里错了吗??
2.通过 clang 可以 查看对应的 汇编代码。其实xcode 的 Product-》Perform Action ->Assemble "" 也就ok了
clang -fobjc-arc -framework Foundation test.m -o test
3 通过 CFGetRetainCount((__bridge CFTypeRef)test2)); 或者
extern uintptr_t _objc_rootRetainCount();
NSLog(@"xxxx %lu",_objc_rootRetainCount(self.array));
可以在 arc 总看到 retaincount 的值。切记 不要依赖这个retaincount 编译器 有很多优化。可能跟你理解的不同。比如 当你 通过一个非 alloc new copy mutableCopy 方法获取一个对象的时候 按照道理是 获取的 autorelease 对象。然后在 retain 。编译器 会优化省略 autorelease 过程。引用计数的思考方式
自己生成的对象,自己所持有
非自己生成的对象,自己也能持有
不在需要自己持有对象时释放
非自己持有的对象 无法释放
方法名称 以 alloc new copy mutableCopy 开头的方法 必须返回给调用者应当持有的对象。
以init 开头的 更加严格 必须返回 id 类型 或者当前类的 类型 或者 子类父类。这个对象不会注册到 autorelease 池里面去。只是
修饰符
_strong
id 类型 和对象类型 默认的修饰符。即:
id xx = [[NSObject alloc] init]; 实际上就等于
id _strong obj = [[NSObject alloc] init ];
简单的说 就是当 strong 修饰符修饰的变量 被赋值的时候。 就相等于 retain 了该对象。 当该修饰符 修饰的变量 抛弃原本指向的对象的时候。 就相当于 release了 该对象。当strong 修饰的变量结束了有效区域的时候。也会release
- MyTest *test = [[MyTest alloc]init];
- MyTest *test2 = test;
- MyTest *test3 = test;
- MyTest *test4 = test;
- MyTest *test5 = test;
- NSLog(@"Retain count is %ld", CFGetRetainCount((__bridge
- CFTypeRef)test));
- test5 = nil;
- NSLog(@"Retain count is %ld", CFGetRetainCount((__bridge
- CFTypeRef)test));
- test4 = [[MyTest alloc]init];
- NSLog(@"Retain count is %ld", CFGetRetainCount((__bridge
- CFTypeRef)test));
如上代码所示。因为默认修饰符是strong 所以 当test 赋值给strong修饰的变量的时候。 就retain了 test。所以第一个输出是5. 当 执行 test5 = nil 的时候。 因为 被修饰符为 strong 的变量 抛弃的对象会release 所以 变成了4. 同样道理 最后 test retainCount 变成了3;(ps:这里要说的是 之前在有的资料看过 非arc 跟 arc 混编的 复杂情况下 有可能导致的内存泄露。 主要是 对象是非arc 创建的 在 arc中使用的情况。 当时 给出的解决方案。就是 用完之后 设置为 nil 就行了。 想想这里的了解。其实有一定道理。当然现在找不到那个资料了所以 也没法实验总结)
_weak
当2个对象互相引用导致引用环的时候就需要weak了。 简单的说就是赋值的时候 不改变 retainCount的概念。当然还有当对象释放之后 会设置为 nil。这也是 _weak 和 __unsafe_unretain 的主要区别。
这里有个需要注意的。当使用__weak 变量的时候。不是简单的访问。 是会调用一个方法 retainWeakReference (可以重写这个非公开方法 用来调试。但正式开发千万别加逻辑。) 书上说 会加入到 autoreleasePool 里面去。可是访问结束查看 autoreleasePool 。在使用访问 __weak的时候 也确实可以查看到 retainCount 增加了1. 这里可以 猜测 是只是访问的那里新建了一个 autoreleasePool池。访问结束 就 已经释放了。
这样的作用是因为 weak 不持有该对象。当访问过程中。可能被释放掉。 这样就能保证访问过程中都是有效状态。
_unsafe_unretained
我能想到的跟 __weak 的区别就是 释放了对象的时候 不设置为 nil。用这个修饰符的对象 不被arc内存管理 所管理。
_autoreleaseing
autorelease 的本质就是 创建一个NsAutoreleasePool 对象。当一个对象调用 autorelease 的时候。 会去获取当前使用的 最内侧(如果有嵌套的池的话)的NsAutoreleasePool对象。然后调用 NsAutoreleasePool对象的一个 类似数组 的addobject 方法。让 NsAutoreleasePool对象来持有这个 autorelease 对象。 当调用 NsAutoreleasePool 的 drain方法的时候。清除引用。 就释放了 autorelease对象。
实际上在arc 中 。编译器有很多优化。让原本是autorelease 的对象 根本就不加入到 NSAutoreleasePool中去。
pd:这里需要注意的是 指针变量 默认的修饰符 是 autoreleaseing 比如 id *xx。 是 autoreleaseing的 而 id xx 是 strong的。
属性
属性修饰符assign__unsafe_unretainedcopy__strong(是retain的复制的新对象)retain__strongstrong__strongunsafe_unretained__unsafe_unretainedweak__weak这里 感觉没有太多的东西需要了解。 只要了解了修饰符 就会知道属性的这些含义了。 需要注意的是 有人喜欢在类里面的方法里面对属性复制的时候 用 下划线开头的变量。这里不建议这样做。 除了 初始化方法 delloc方法,以及 set get 方法内部。 其他地方 对属性赋值的时候 尽量用属性访问。这是为了维护好属性的 copy strong 等。另外这里测试的时候 发现 如果在方法里面 有个 __weak属性 每次使用 属性都会导致retainCount +1. 查看汇编代码 有个
_objc_retainAutoreleasedReturnValue 方法被调用了。完全不知道为什么。。
看了下 _objc_autoreleasedReturnValue 函数 返回 注册到 autoreleasepool 里面的对象。 但是 跟 autorelease 函数又不同。 如果 _objc_autoreleasedReturnValue 方法之后 会立即调用 _objc_retainAutoreleasedReturnValue 就不将对象注册到 autoreleasepool 中。而是直接传递到方法或者函数的调用方。 _objc_retainAutoreleasedReturnValue 和 objc_retain 函数不同。 这个作用 就是 上面说到的。 对于不是 new alloc copy mutablecopy 开头的方法。按道理返回的对象是 autorelease 然后在retain 。这个机制就优化了这里的代码
- IOS内存管理小结
- IOS内存管理小结
- ios 内存小结
- ios 内存小结
- 内存小结
- iOS小结
- C++内存使用小结
- 共享内存读写小结
- IE内存泄露小结
- 内存对齐用法小结
- 内存故障小结
- 内存泄露小结
- android 内存泄露 小结
- 内存布局小结
- VxWorks 内存结构小结
- C++ 内存管理小结
- GDI内存泄露小结
- android内存管理小结
- FastCGI简介
- 我的Docker学习之旅<三>
- httppost 远程服务器返回错误: (400) 错误的请求错误
- hdu 5456 Matches Puzzle Game(记忆化搜索)
- 自定义Tabbar封装
- ios 内存小结
- 链路层介绍,转载自实验楼
- ERROR ITMS-90086 有效处理方式
- 当幸福来敲门
- 网赛 HDU 5444 Elven Postman
- Nginx与PHP(FastCGI)的安装、配置与优化
- 由appcampat 的思考
- linux动态链接
- java String 和 int 相互转换