简体   繁体   English

目标C - ARC,内存管理和performSelectorInBackground?

[英]Objective C - ARC, memory management and performSelectorInBackground?

Does ARC no longer require @autoreleasepool on methods invoked in a background thread? ARC是否不再需要在后台线程中调用的方法上使用@autoreleasepool The following code suppose to cause a memory leak unless doStuff is wrapped with an @autorelease pool, but when I run instruments it shows that User gets allocated and it gets deallocated at the end of the runloop. 下面的代码假设导致内存泄漏,除非doStuff包含@autorelease池,但是当我运行instrument时它会显示User被分配并在runloop结束时被解除分配。

- (IBAction)buttonClicked:(id)sender {
    [self performSelectorInBackground:@selector(doStuff) withObject:nil];
}

- (void)doStuff {
    User *user = [[User alloc] init];
    NSLog(@"%@", user);
}

While there might be hints to an existing autorelease pool in NSThread's implementation there is no such guarantee the documentation. 虽然在NSThread的实现中可能存在对现有自动释放池的提示,但是没有这样的文档保证。 In contrary, the documentation explicitly states otherwise: 相反,文档明确指出:

performSelectorInBackground:withObject: performSelectorInBackground:withObject:

The method represented by aSelector must set up the thread environment just as you would for any other new thread in your program. aSelector表示的方法必须像程序中的任何其他新线程一样设置线程环境。

Threading Programming Guide 线程编程指南

If your application uses the managed memory model [MRC and ARC, as opposed to Garbage Collection], creating an autorelease pool should be the first thing you do in your thread entry routine. 如果您的应用程序使用托管内存模型[MRC和ARC,而不是垃圾收集],则创建自动释放池应该是您在线程入口例程中首先要做的事情。

Conclusion: While in some specific scenarios there might be an autorelease pool in place it's not advisable to rely on this fact. 结论:虽然在某些特定情况下可能存在自动释放池,但不建议依赖此事实。 It's undocumented behavior and can change with every release of the OS or other circumstances. 它是未记录的行为,可以随操作系统的每个版本或其他情况而改变。 It should generally be avoided in shipping code. 通常应该在运输代码中避免。

I used the following test app: 我使用了以下测试应用程序:

#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@end

#import "ViewController.h"
@implementation ViewController
- (void)viewDidLoad{
    [super viewDidLoad];
    [self performSelectorInBackground:@selector(doStuff) withObject:nil];
}
- (void)doStuff {
    NSMutableArray *ar = [NSMutableArray array];
    for (int i=0; i<1000000; i++) {
        ar[i] = [NSString stringWithFormat:@"%i", i];
    }
}
@end

Profiling it with the Allocation instrument, I get the following result: 使用分配工具对其进行分析,得到以下结果:
在此输入图像描述
In the 8th line of the call tree, an autorelease pool is used, although I did not set up one in my code. 在调用树的第8行,使用自动释放池,虽然我没有在我的代码中设置一个。 Also, the memory allocated by the background thread seems to be released. 此外,后台线程分配的内存似乎已被释放。
It thus looks as if the background thread has an autorelease pool installed. 因此看起来好像后台线程安装了自动释放池。

EDIT (see comment below): 编辑 (见下面的评论):

This does not mean, however, that it is not necessary to install autorelease pools for threads, since the behavior shown above is not documented, as far as I know. 但是,这并不意味着没有必要为线程安装自动释放池,因为据我所知,上面显示的行为没有记录。

Actually, that code is supposed to leak memory (under MRC) if you don't add an autorelease (which is pretty much just asking for trouble). 实际上,如果您不添加autorelease (这几乎只是在寻找麻烦),该代码应该泄漏内存(在MRC下)。 But I'm going to answer your question as you asked it anyways. 但是,无论如何,我会回答你的问题。

ARC is supposed to eliminate the need for any sort of memory management (except for blocks and a lot of other gotchas, but whatever). ARC应该不需要任何类型的内存管理(除了块和许多其他陷阱,但无论如何)。 But there are still autoreleased objects. 但仍有自动释放的对象。 @autoreleasepool is particularly useful in tight loops, etc. There are still pools to drain, you just don't have to add autorelease to objects yourself. @autoreleasepool在紧密循环等方面特别有用。还有池要流失,你不必自己添加autorelease对象。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM