NSThread现在会自动创建autoreleasepool吗?

编程入门 行业动态 更新时间:2024-10-27 21:14:03
本文介绍了NSThread现在会自动创建autoreleasepool吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我有这样的测试代码

- (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]); }

我没有为自己的线程创建任何自动释放池,但是当线程退出时,对象我的只是dealloc.why?

I did not create any autoreleasepool for my own thread, but when the thread exit, object "my" just dealloc.why?

即使我将测试代码更改如下

even though I change my test code as below

- (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]); }

我创建了自己的自动释放池,但在线程退出时不会耗尽它。对象我的仍然可以dealloc。为什么?

I create my own autoreleasepool but not drain it when the thread exit. object "my" can still dealloc anyway. why?

我使用Xcode5而不使用ARC

I use Xcode5 and not using ARC

推荐答案

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

It's not documented, but the answer appears to be Yes, on OS X 10.9+ and iOS 7+.

Objective-C运行时是 open-source 所以你可以阅读源代码来看看发生了什么。如果在当前线程上执行 autorelease 而没有池,则运行时的最新版本(646,OS X 10.10和iOS 8附带)确实会添加池。在 NSObject.mm 中:

The Objective-C runtime is open-source so you can read the source to see what's going on. The latest version of the runtime (646, which shipped with OS X 10.10 and iOS 8) does indeed add a pool if you perform an autorelease without a pool on the current thread. In 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 环境变量(默认情况下没有设置),当autorelease完成没有池时,它也会设置自动释放堆栈,然后推送池(推送 POOL_SENTINEL )。

This function is called when you push the first pool (in which case the thing pushed is POOL_SENTINEL), or you autorelease with no pool. When the first pool is pushed, it sets up the autorelease stack. But as you see from the code, as long as the DebugMissingPools environmental variable is not set (it's not set by default), when autorelease is done with no pool, it also sets up the autorelease stack, and then pushes a pool (pushes a POOL_SENTINEL).

同样,(它有点)很难跟随而不看其他代码,但这是相关部分)当线程被销毁(并且线程局部存储被销毁)时,它会释放自动释放堆栈中的所有内容(这就是 pop(0); 确实如此)所以它不依赖于用户弹出最后一个池:

Similarly, (it's a little hard to follow without looking at the other code, but this is the relevant part) when the thread is destroyed (and the Thread-Local Storage is destroyed), it releases everything in the autorelease stack (that's what the pop(0); does) so it doesn't rely on the user to pop the last pool:

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 :

The previous version of the runtime (551.1, which came with OS X 10.9 and iOS 7), also did this, as you can see from its 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),没有:

But the version before that (532.2, which came with OS X 10.8 and 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 s,而不仅仅是 NSThread s。

Note that the above works for any pthreads, not just NSThreads.

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

So basically, if you are running on OS X 10.9+ or iOS 7+, autoreleasing on a thread without a pool should not lead to a leak. This is not documented and is an internal implementation detail, so be careful relying on this as Apple could change it in a future OS. However, I don't see any reason why they would remove this feature as it is simple and only has benefits and no downsides, unless they completely re-write the way autorelease pools work or something.

更多推荐

NSThread现在会自动创建autoreleasepool吗?

本文发布于:2023-10-13 14:19:20,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1488190.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:NSThread   autoreleasepool

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!