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

前端之家收集整理的这篇文章主要介绍了ios – NSThread现在会自动创建autoreleasepool吗?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有这样的测试代码
  1. - (void)viewDidLoad
  2. {
  3. [super viewDidLoad];
  4. NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(test) object:nil];
  5. [thread start];
  6. }
  7.  
  8. -(void)test
  9. {
  10. MyClass *my = [[[MyClass alloc] init] autorelease];
  11. NSLog(@"%@",[my description]);
  12. }

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

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

  1. - (void)viewDidLoad
  2. {
  3. [super viewDidLoad];
  4.  
  5. NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(test) object:nil];
  6. [thread start];
  7. }
  8.  
  9. -(void)test
  10. {
  11. NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
  12. MyClass *my = [[[MyClass alloc] init] autorelease];
  13. NSLog(@"%@",[my description]);
  14. }

我创建了自己的autoreleasepool但在线程退出时不会将其耗尽.对象“我的”仍然可以dealloc.为什么?

我使用Xcode5而不使用ARC

解决方法

它没有记录,但在OS X 10.9和iOS 7上答案似乎是肯定的.

Objective-C运行时为open-source,因此您可以阅读源代码以查看正在进行的操作.如果在当前线程上执行没有池的自动释放,则运行时的最新版本(646,OS X 10.10和iOS 8附带)确实会添加池.在NSObject.mm

  1. static __attribute__((noinline))
  2. id *autoreleaseNoPage(id obj)
  3. {
  4. // No pool in place.
  5. assert(!hotPage());
  6.  
  7. if (obj != POOL_SENTINEL && DebugMissingPools) {
  8. // We are pushing an object with no pool in place,// and no-pool debugging was requested by environment.
  9. _objc_inform("MISSING POOLS: Object %p of class %s "
  10. "autoreleased with no pool in place - "
  11. "just leaking - break on "
  12. "objc_autoreleaseNoPool() to debug",(void*)obj,object_getClassName(obj));
  13. objc_autoreleaseNoPool(obj);
  14. return nil;
  15. }
  16.  
  17. // Install the first page.
  18. AutoreleasePoolPage *page = new AutoreleasePoolPage(nil);
  19. setHotPage(page);
  20.  
  21. // Push an autorelease pool boundary if it wasn't already requested.
  22. if (obj != POOL_SENTINEL) {
  23. page->add(POOL_SENTINEL);
  24. }
  25.  
  26. // Push the requested object.
  27. return page->add(obj);
  28. }

当您推送第一个池时(在这种情况下推送的东西是POOL_SENTINEL),或者您在没有池的情况下自动释放,就会调用函数.当推送第一个池时,它会设置自动释放堆栈.但是从代码中可以看出,只要未设置DebugMissingPools环境变量(默认情况下不设置),当autorelease完成没有池时,它也会设置自动释放堆栈,然后推送池(推送一个池) POOL_SENTINEL).

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

  1. static void tls_dealloc(void *p)
  2. {
  3. // reinstate TLS value while we work
  4. setHotPage((AutoreleasePoolPage *)p);
  5. pop(0);
  6. setHotPage(nil);
  7. }

之前版本的运行时(551.1,OS X 10.9和iOS 7附带)也是这样做的,你可以从NSObject.mm看到:

  1. static __attribute__((noinline))
  2. id *autoreleaseSlow(id obj)
  3. {
  4. AutoreleasePoolPage *page;
  5. page = hotPage();
  6.  
  7. // The code below assumes some cases are handled by autoreleaseFast()
  8. assert(!page || page->full());
  9.  
  10. if (!page) {
  11. // No pool. Silently push one.
  12. assert(obj != POOL_SENTINEL);
  13.  
  14. if (DebugMissingPools) {
  15. _objc_inform("MISSING POOLS: Object %p of class %s "
  16. "autoreleased with no pool in place - "
  17. "just leaking - break on "
  18. "objc_autoreleaseNoPool() to debug",object_getClassName(obj));
  19. objc_autoreleaseNoPool(obj);
  20. return nil;
  21. }
  22.  
  23. push();
  24. page = hotPage();
  25. }
  26.  
  27. do {
  28. if (page->child) page = page->child;
  29. else page = new AutoreleasePoolPage(page);
  30. } while (page->full());
  31.  
  32. setHotPage(page);
  33. return page->add(obj);
  34. }

但之前的版本(532.2,OS X 10.8和iOS 6附带),does not

  1. static __attribute__((noinline))
  2. id *autoreleaseSlow(id obj)
  3. {
  4. AutoreleasePoolPage *page;
  5. page = hotPage();
  6.  
  7. // The code below assumes some cases are handled by autoreleaseFast()
  8. assert(!page || page->full());
  9.  
  10. if (!page) {
  11. assert(obj != POOL_SENTINEL);
  12. _objc_inform("Object %p of class %s autoreleased "
  13. "with no pool in place - just leaking - "
  14. "break on objc_autoreleaseNoPool() to debug",obj,object_getClassName(obj));
  15. objc_autoreleaseNoPool(obj);
  16. return NULL;
  17. }
  18.  
  19. do {
  20. if (page->child) page = page->child;
  21. else page = new AutoreleasePoolPage(page);
  22. } while (page->full());
  23.  
  24. setHotPage(page);
  25. return page->add(obj);
  26. }

请注意,上述内容适用于任何pthread,而不仅仅适用于NSThreads.

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

猜你在找的iOS相关文章