gpt4 book ai didi

ios - NSThread 现在会自动创建 autoreleasepool 吗?

转载 作者:可可西里 更新时间:2023-11-01 03:05:15 25 4
gpt4 key购买 nike

我有这样的测试代码

- (void)viewDidLoad
{
[super viewDidLoad];
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(test) object:nil];
[thread start];
}

-(void)test
{
MyClass *my = [[[MyClass alloc] init] autorelease];
NSLog(@"%@",[my description]);
}

我没有为我自己的线程创建任何自动释放池,但是当线程退出时,对象“my”只是dealloc。为什么?

即使我改变了我的测试代码如下

- (void)viewDidLoad
{
[super viewDidLoad];

NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(test) object:nil];
[thread start];
}

-(void)test
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
MyClass *my = [[[MyClass alloc] init] autorelease];
NSLog(@"%@",[my description]);
}

我创建了自己的 autoreleasepool 但在线程退出时不会耗尽它。无论如何,对象“我的”仍然可以解除分配。为什么?

我使用 Xcode5 而不是使用 ARC

最佳答案

它没有记录在案,但答案似乎是,在 OS X 10.9+ 和 iOS 7+ 上。

Objective-C 运行时是 open-source因此您可以阅读源代码以了解发生了什么。如果您在当前线程上执行没有池的 autorelease,最新版本的运行时(646,随 OS X 10.10 和 iOS 8 一起提供)确实会添加一个池。在 NSObject.mm :

static __attribute__((noinline))
id *autoreleaseNoPage(id obj)
{
// No pool in place.
assert(!hotPage());

if (obj != POOL_SENTINEL && DebugMissingPools) {
// We are pushing an object with no pool in place,
// and no-pool debugging was requested by environment.
_objc_inform("MISSING POOLS: Object %p of class %s "
"autoreleased with no pool in place - "
"just leaking - break on "
"objc_autoreleaseNoPool() to debug",
(void*)obj, object_getClassName(obj));
objc_autoreleaseNoPool(obj);
return nil;
}

// Install the first page.
AutoreleasePoolPage *page = new AutoreleasePoolPage(nil);
setHotPage(page);

// Push an autorelease pool boundary if it wasn't already requested.
if (obj != POOL_SENTINEL) {
page->add(POOL_SENTINEL);
}

// Push the requested object.
return page->add(obj);
}

当您推送第一个池时调用此函数(在这种情况下推送的是 POOL_SENTINEL),或者您在没有池的情况下自动释放。当第一个池被推送时,它会设置自动释放堆栈。但正如您从代码中看到的那样,只要未设置 DebugMissingPools 环境变量(默认情况下未设置),当自动释放完成时没有池,它也会设置自动释放堆栈,并且然后推送一个池(推送一个POOL_SENTINEL)。

类似地,(如果不看其他代码就有点难以理解,但这是相关部分)当线程被销毁(并且线程本地存储被销毁)时,它会释放自动释放堆栈中的所有内容(这就是 pop(0); 所做的)所以它不依赖于用户弹出最后一个池:

static void tls_dealloc(void *p) 
{
// reinstate TLS value while we work
setHotPage((AutoreleasePoolPage *)p);
pop(0);
setHotPage(nil);
}

以前版本的运行时(551.1,随 OS X 10.9 和 iOS 7 一起提供)也这样做了,正如您从它的 NSObject.mm 中看到的那样。 :

static __attribute__((noinline))
id *autoreleaseSlow(id obj)
{
AutoreleasePoolPage *page;
page = hotPage();

// The code below assumes some cases are handled by autoreleaseFast()
assert(!page || page->full());

if (!page) {
// No pool. Silently push one.
assert(obj != POOL_SENTINEL);

if (DebugMissingPools) {
_objc_inform("MISSING POOLS: Object %p of class %s "
"autoreleased with no pool in place - "
"just leaking - break on "
"objc_autoreleaseNoPool() to debug",
(void*)obj, object_getClassName(obj));
objc_autoreleaseNoPool(obj);
return nil;
}

push();
page = hotPage();
}

do {
if (page->child) page = page->child;
else page = new AutoreleasePoolPage(page);
} while (page->full());

setHotPage(page);
return page->add(obj);
}

但之前的版本(532.2,随 OS X 10.8 和 iOS 6 一起提供),does not :

static __attribute__((noinline))
id *autoreleaseSlow(id obj)
{
AutoreleasePoolPage *page;
page = hotPage();

// The code below assumes some cases are handled by autoreleaseFast()
assert(!page || page->full());

if (!page) {
assert(obj != POOL_SENTINEL);
_objc_inform("Object %p of class %s autoreleased "
"with no pool in place - just leaking - "
"break on objc_autoreleaseNoPool() to debug",
obj, object_getClassName(obj));
objc_autoreleaseNoPool(obj);
return NULL;
}

do {
if (page->child) page = page->child;
else page = new AutoreleasePoolPage(page);
} while (page->full());

setHotPage(page);
return page->add(obj);
}

请注意,以上内容适用于任何 pthread,而不仅仅是 NSThread

所以基本上,如果您在 OS X 10.9+ 或 iOS 7+ 上运行,在没有池的线程上自动释放应该不会导致泄漏。这没有记录并且是一个内部实现细节,因此请谨慎依赖它,因为 Apple 可能会在未来的操作系统中更改它。但是,我看不出他们为什么要删除此功能,因为它很简单,只有好处而没有缺点,除非他们完全重写自动释放池的工作方式或其他东西。

关于ios - NSThread 现在会自动创建 autoreleasepool 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24952549/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com