iOS面试基础知识点iOS开发·内存相关

iOS-底层原理-内存管理

2021-12-29  本文已影响0人  贝勒老爷
一使用CADisplayLink、NSTimer有什么注意点?

范例代码

@property (strong, nonatomic) CADisplayLink *link;

// 1.发生内存泄露
self.link = [CADisplayLink displayLinkWithTarget:self selector:@selector(linkTest)];
[self.link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];

- (void)linkTest {
    NSLog(@"%s", __func__);
}

@property (strong, nonatomic) NSTimer *timer;

// 1.会内存泄露
self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timerTest) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];

- (void)timerTest {
    NSLog(@"%s", __func__);
}

二 介绍下内存的几大区域
三 讲一下你对 iOS 内存管理的理解
四 ARC 都帮我们做了什么?

首先利用LLVM,帮我们自动生成release,retain,autorelease代码
需要runtime运行时做一些事情
即ARC时LLVM编译器和Runtime系统相互协作的一个结果

五 weak指针的实现原理

将弱引用存储到一个哈希表里,当对象要销毁时,就会取出当前对象的弱引用表,将该表存储的弱引用都给清除掉

六 autorelease对象在什么时机会被调用release

iOS在主线程的Runloop中注册了2个Observer

代码例子如下

- (void)viewDidLoad {
    [super viewDidLoad];

    Person *person = [[Person alloc] init];
    NSLog(@"%s", __func__);
}

这个Person什么时候调用release,是由RunLoop来控制的
它可能是在某次RunLoop循环中,RunLoop休眠之前调用了release
Person *person = [[[Person alloc] init] autorelease];

6.1 包含在@autoreleasepool中,则在pop的时候,即@@autoreleasepool作用域结束的时候销毁。
七 方法里有局部对象, 出了方法后会立即释放吗

autorelease对象:在它所在的线程对应的本次runloop即将进入休眠时释放

非autorelease对象:出了作用域就释放

八 思考以下2段代码能发生什么事?有什么区别?
@property(nonatomic,strong)NSString *name;
// @property(nonatomic,copy)NSString *name;
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
for (int i = 0; i < 1000; i++) {
    dispatch_async(queue, ^{
        // 加锁
        self.name = [NSString stringWithFormat:@"abcdefghijk"];
        // 解锁
    });
}

运行结果

image

因为给self.name赋值,实际上是调用其set方法

- (void)setName:(NSString *)name {
    if (_name != name) {
        [_name release];
        _name = [name retain];
    }
}

set方法内部,会先执行release操作,然后再执行retain操作,如果是多个线程同时执行set方法,则会造成释放2次的情况,所有导致坏内存访问。

代码二

dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
for (int i = 0; i < 1000; i++) {
    dispatch_async(queue, ^{
        self.name = [NSString stringWithFormat:@"abc"];
    });
}

执行结果:正常访问没有奔溃报错。

NSString *str1 = [NSString stringWithFormat:@"abc"];
NSString *str2 = [NSString stringWithFormat:@"123abc11111111"];

NSLog(@"%@ %@", [str1 class], [str2 class]);
NSLog(@"%p %p", str1,str2);

运行结果

image

因为一个是NSTaggedPointerString,一个是__NSCFString

上一篇 下一篇

猜你喜欢

热点阅读