主要目的就是为了检测程序是否存在内存泄露
- MRC
target -> build setting -> 搜索 automatic reference counting
截屏2020-06-01下午4.32.53.png
1. 静态内存分析(Analyze)
- 概念:
静态内存分析是不运行程序,直接对代码进行分析.
根据代码的上下文的语法结构,来分析内存状况
- 作用:
调整环境到MRC
逻辑错误:访问未初始化的变量或者野指针等;
声明错误:从未使用过的对象;
内存管理错误:如内存泄漏等;(MRC&ARC)
- 缺点:
不一定准确,但是如果发现有提示,那么去结合上下文看一下,这里的代码是否有问题
- 场景演练(OC):
MRC 下桥接
Foundation 到 CoreFoundation框架的数据类型转换
强制数据类型转换, 不会移交对象内存管理所有权
CoreFoundation 到 Foundation框架的数据类型转换
强制数据类型转换, 不会移交对象内存管理所有权
MRC下的静态分析
// > 逻辑错误:访问未初始化的变量或
NSObject *obj;
NSLog(@"%@", obj);
![](https://i-blog.csdnimg.cn/blog_migrate/934783abda60908868d532463361d35f.png)
// 野指针等;
NSObject *obj = [[NSObject alloc] init];
[obj release];
NSLog(@"%@",obj);
![](https://i-blog.csdnimg.cn/blog_migrate/caba1f376ff76b265c5b9d02874fc666.png)
// > 声明错误:从未使用过的对象;
NSObject *obj = [[[NSObject alloc] init] autorelease];
![](https://i-blog.csdnimg.cn/blog_migrate/c37c4ea25b8d871b19cf31c8b79b2707.png)
// 测试不准确的地方
NSObject *obj = [self lost];
NSLog(@"%@", obj);
[obj release];
}
- (NSObject *)lost
{
return [[NSObject alloc]init];
}
![](https://i-blog.csdnimg.cn/blog_migrate/d37acf0f91fe5a47059fa101b5069846.png)
使用Corefoundation的框架内容要记得释放
![](https://i-blog.csdnimg.cn/blog_migrate/3802d1903b781c2e1f3184836e4ad483.png)
MRC下的桥接
- (void)mrc
{
//MRC下桥接
//Foundation 到 CoreFoundation框架的数据类型转换
NSString *str = [[NSString alloc] init];
// CFStringRef , 这种转换, 属于直接转换, 不会移交对象的内存管理权
CFStringRef strRef = (CFStringRef)str;
NSLog(@"%@", strRef);
[str release];
//CoreFoundation 往 Foundation框架的数据类型转换
CFStringRef strRef2 = CFStringCreateWithCString(CFAllocatorGetDefault(), "123", kCFStringEncodingUTF8);
// 这种转换, 属于直接转换, 不会移交对象的内存管理权
NSString *str2 = (NSString *)strRef2;
CFRelease(strRef2);
}
ARC下的桥接
//Foundation 到 CoreFoundation框架的数据类型转换
NSString *str = [[NSString alloc] init];
// (__bridge CFStringRef) 等同于 MRC下面的直接转换, 不会移交对象的内存管理权
CFStringRef strRef = (__bridge CFStringRef)(str);
NSLog(@"%@", strRef);
// CFBridgingRetain == __bridge_retained CFStringRef
// 这种方式转换, 会移交对象的内存管理权
CFStringRef strRef2 = (__bridge_retained CFStringRef)(str);
NSLog(@"%@", strRef2);
CFRelease(strRef2);
//CoreFoundation 到 Foundation框架的数据类型转换
CFStringRef strRef3 = CFStringCreateWithCString(CFAllocatorGetDefault(), "123", kCFStringEncodingUTF8);
// __bridge NSString * 等同于 MRC下面的直接转换, 不会移交对象的内存管理权, 还是释放原来的对象
// NSString *str3 = (__bridge NSString*)(strRef3);
// NSLog(@"%@", str3);
// CFRelease(strRef3);
// CFBridgingRelease == __bridge_transfer NSString *
// 这种方式转换, 会移交对象的内存管理权
NSString *str4 = (__bridge_transfer NSString *)(strRef3);
NSLog(@"%@", str4);
关于Swift中使用CoreFoundation 数据类型
使用了"类型重映射"机制, 转换成为了能够自动管理内存的对象, 不需要我们手动释放
内存分配
作用
查看是内存的分配情况
查看内存是否有释放
- UIImage 的两种创建方法测试
- 加载UIImage的不同方式
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?)
{
// 通过 named 创建的图片资源, 不会被释放, 在内存中, 只有一份
//let imageNew = UIImage(named: "liudog.png")
let path = Bundle.main.path(forResource: "liudog.jpg", ofType: nil)
//图片没有缓存,可以被释放,
let imageNew = UIImage(contentsOfFile: path!)
if imageView == nil
{
return
}
imageView.image = imageNew
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?)
{
if imageView == nil
{
return
}
imageView.removeFromSuperview()
}
概念解释
Anonymous VM(匿名虚拟内存)是系统为程序预留的、可能会立即被重复使用的一部分可用内存
图片使用技巧
图片在沙盒中的存在形式
1.如果项目的Deployment Target <= 6.x (不支持图片压缩), 所有图片直接暴露在沙盒的资源包(main Bundle), 不会压缩到Assets.car文件
- 如果项目的Deployment Target >= 7.x (支持图片压缩)
1 放在Images.xcassets里面的所有图片会压缩到Assets.car文件, 不会直接暴露在沙盒的资源包(main Bundle)
2 没有放在Images.xcassets里面的所有图片会直接暴露在沙盒的资源包(main Bundle), 不会压缩到Assets.car文件
- 使用对比
- 会压缩到Assets.car文件, 没有直接暴露在沙盒的资源包(main Bundle)条件 : "Deployment Target >= 7.x" 并且是 "放在Images.xcassets里面的所有图片"影响 : 无法得到图片的全路径, 只能通过图片名(imageNamed:方法)来加载图片, 永远会有缓存
- 不会压缩到Assets.car文件, 直接暴露在沙盒的资源包(main Bundle)
** 条件 :** 除1> 以外的所有情况
** 影响 :** 可以得到图片的全路径, 可以通过全路径(imageWithContentsOfFile:方法)来加载图片, 不会有缓存
- 结论
- 小图片\使用频率比较高的图片,放在Images.xcassets里面
- 大图片\使用频率比较低的图片(一次性的图片, 比如版本新特性的图片)
动态内存分析
- 作用 :检测程序在运行过程中是否存在内存泄露
-
演练:> 模拟循环引用, 测试内存泄露
Leaks
4. 内存使用总结
如何让程序尽量减少内存泄漏
- 1.非ARC
- Foundation对象(OC对象) : 只要方法中包含了alloc\new\copy\mutableCopy\retain等关键字, 那么这些方法产生的对象, 就必须在不再使用的时候调用1次release或者1次autorelease
- CoreFoundation对象(C对象) : 只要函数中包含了create\new\copy\retain等关键字, 那么这些方法产生的对象, 就必须在不再使用的时候调用1次CFRelease或者其他release函数
- 2.ARC
- 只自动管理OC对象, 不会自动管理C语言对象
- CoreFoundation对象(C对象) : 只要函数中包含了create\new\copy\retain等关键字, 那么这些方法产生的对象, 就必须在不再使用的时候调用1次CFRelease或者其他release函数
- 如果是swift里面, 使用* CoreFoundation对象(C对象) , 不需要手动释放. 因为使用了"类型重映射"机制, 可以把对象转换成为自动管理内存的对象