8

我正在使用 NSOperation 和 NSOperationQueue 执行一系列操作,所有操作都相互依赖(2 对 1、3 对 2 等)。创建操作后,我设置了依赖项。队列完成时我遇到了问题:程序在代码的 _release 部分崩溃,显然是在 NSOperations 被释放时。请注意,它们都在队列的最后被释放,因为只有在最后一个依赖于倒数第二个之后,它们才能被释放。如果我删除任何依赖项,代码运行良好。如果我将 waitUntilFinished: 更改为 NO,它会崩溃,如果它是 YES,它不会。

我已将问题隔离到以下代码,该代码不使用我的任何自定义类。默认情况下,NSOperation 是一个完全不做任何事情的类。然而,当所有操作都完成后,这仍然会崩溃。因此,看来我没有正确使用 NSOperationQueue 但看不出有什么问题。我在 10.9 上运行,我注意到通常 Maverick 10.9 比 10.8 对这些问题更敏感。

我使用菜单项从主线程调用此方法:

- (void) testOperations:(id)object  
{

        NSOperationQueue* queue = [ [ NSOperationQueue alloc ] init ];

        NSMutableArray* array = [ NSMutableArray array ];
        for ( int i = 0; i < 10000; i++)
            [ array addObject: [[[ NSOperation alloc ] init ] autorelease ] ];

        for ( int i = 1; i < [ array count ]; i++)
            [[ array objectAtIndex:i ] addDependency:[array objectAtIndex:i-1]]; // remove this and no crash

        [ queue addOperations: array waitUntilFinished:NO ]; // Change to YES, no crash
        [ queue autorelease ]; // or release, it does not make a difference, in fact leaking the memory makes no difference: the code crashes when the queue is removing the NSOperations
}

每次都会崩溃: bool objc::DenseMapBase >, objc_object*, unsigned long, objc::DenseMapInfo, true>: (EXC_BAD_ACCESS)

完整的堆栈是:

#0  0x9104d81b in objc::DenseMapBase<objc::DenseMap<objc_object*, unsigned long, true, objc::DenseMapInfo<objc_object*> >, objc_object*, unsigned long, objc::DenseMapInfo<objc_object*>, true>::find(objc_object* const&) ()
#1  0x910384e3 in _objc_rootReleaseWasZero ()
#2  0x9104d5d9 in -[NSObject release] ()
#3  0x99e41224 in CFRelease ()
#4  0x99e56277 in -[__NSArrayM dealloc] ()
#5  0x9104d5ef in -[NSObject release] ()
#6  0x97f62b22 in -[__NSOperationInternal dealloc] ()
#7  0x9104d5ef in -[NSObject release] ()
#8  0x97f62ac8 in -[NSOperation dealloc] ()
#9  0x9104d5ef in -[NSObject release] ()
#10 0x99e41224 in CFRelease ()
#11 0x99e56277 in -[__NSArrayM dealloc] ()
#12 0x9104d5ef in -[NSObject release] ()
#13 0x97f62b22 in -[__NSOperationInternal dealloc] ()
#14 0x9104d5ef in -[NSObject release] ()
#15 0x97f62ac8 in -[NSOperation dealloc] ()
#16 0x9104d5ef in -[NSObject release] ()
#17 0x99e41224 in CFRelease ()
#18 0x99e56277 in -[__NSArrayM dealloc] ()
#19 0x9104d5ef in -[NSObject release] ()
#20 0x97f62b22 in -[__NSOperationInternal dealloc] ()
#21 0x9104d5ef in -[NSObject release] ()
#22 0x97f62ac8 in -[NSOperation dealloc] ()
#23 0x9104d5ef in -[NSObject release] ()
#24 0x99e41224 in CFRelease ()
#25 0x99e56277 in -[__NSArrayM dealloc] ()
#26 0x9104d5ef in -[NSObject release] ()
#27 0x97f62b22 in -[__NSOperationInternal dealloc] ()
#28 0x9104d5ef in -[NSObject release] ()
#29 0x97f62ac8 in -[NSOperation dealloc] ()
#30 0x9104d5ef in -[NSObject release] ()
#31 0x99e41224 in CFRelease ()
#32 0x99e56277 in -[__NSArrayM dealloc] ()
#33 0x9104d5ef in -[NSObject release] ()
#34 0x97f62b22 in -[__NSOperationInternal dealloc] ()
#35 0x9104d5ef in -[NSObject release] ()
#36 0x97f62ac8 in -[NSOperation dealloc] ()
#37 0x9104d5ef in -[NSObject release] ()
#38 0x99e41224 in CFRelease ()
#39 0x99e56277 in -[__NSArrayM dealloc] ()
#40 0x9104d5ef in -[NSObject release] ()
#41 0x97f62b22 in -[__NSOperationInternal dealloc] ()
#42 0x9104d5ef in -[NSObject release] ()
#43 0x97f62ac8 in -[NSOperation dealloc] ()
#44 0x9104d5ef in -[NSObject release] ()
#45 0x99e41224 in CFRelease ()
#46 0x99e56277 in -[__NSArrayM dealloc] ()
#47 0x9104d5ef in -[NSObject release] ()
#48 0x97f62b22 in -[__NSOperationInternal dealloc] ()
#49 0x9104d5ef in -[NSObject release] ()
#50 0x97f62ac8 in -[NSOperation dealloc] ()
#10722  0x9104d5ef in -[NSObject release] ()
#10723  0x97f62b22 in -[__NSOperationInternal dealloc] ()
#10724  0x9104d5ef in -[NSObject release] ()
#10725  0x97f62ac8 in -[NSOperation dealloc] ()
#10726  0x9104d5ef in -[NSObject release] ()
#10727  0x99e41224 in CFRelease ()
#10728  0x99e56277 in -[__NSArrayM dealloc] ()
#10729  0x9104d5ef in -[NSObject release] ()
#10730  0x97f62b22 in -[__NSOperationInternal dealloc] ()
#10731  0x9104d5ef in -[NSObject release] ()
#10732  0x97f62ac8 in -[NSOperation dealloc] ()
#10733  0x9104d5ef in -[NSObject release] ()
#10734  0x99e41224 in CFRelease ()
#10735  0x99e56277 in -[__NSArrayM dealloc] ()
#10736  0x9104d5ef in -[NSObject release] ()
#10737  0x97f62b22 in -[__NSOperationInternal dealloc] ()
#10738  0x9104d5ef in -[NSObject release] ()
#10739  0x97f62ac8 in -[NSOperation dealloc] ()
#10740  0x9104d5ef in -[NSObject release] ()
#10741  0x99e41224 in CFRelease ()
#10742  0x99e56277 in -[__NSArrayM dealloc] ()
#10743  0x9104d5ef in -[NSObject release] ()
#10744  0x97f62b22 in -[__NSOperationInternal dealloc] ()
#10745  0x9104d5ef in -[NSObject release] ()
#10746  0x97f62ac8 in -[NSOperation dealloc] ()
#10747  0x9104d5ef in -[NSObject release] ()
#10748  0x99e41224 in CFRelease ()
#10749  0x99e56277 in -[__NSArrayM dealloc] ()
#10750  0x9104d5ef in -[NSObject release] ()
#10751  0x97f62b22 in -[__NSOperationInternal dealloc] ()
#10752  0x9104d5ef in -[NSObject release] ()
#10753  0x97f62ac8 in -[NSOperation dealloc] ()
#10754  0x9104d5ef in -[NSObject release] ()
#10755  0x99e41224 in CFRelease ()
#10756  0x99e56277 in -[__NSArrayM dealloc] ()
#10757  0x9104d5ef in -[NSObject release] ()
#10758  0x97f62b22 in -[__NSOperationInternal dealloc] ()
#10759  0x9104d5ef in -[NSObject release] ()
#10760  0x97f62ac8 in -[NSOperation dealloc] ()
#10761  0x9104d5ef in -[NSObject release] ()
#10762  0x99e41224 in CFRelease ()
#10763  0x99e56277 in -[__NSArrayM dealloc] ()
#10764  0x9104d5ef in -[NSObject release] ()
#10765  0x97f62b22 in -[__NSOperationInternal dealloc] ()
#10766  0x9104d5ef in -[NSObject release] ()
#10767  0x97f62ac8 in -[NSOperation dealloc] ()
#10768  0x9104d5ef in -[NSObject release] ()
#10769  0x99e41224 in CFRelease ()
#10770  0x99e56277 in -[__NSArrayM dealloc] ()
#10771  0x9104d5ef in -[NSObject release] ()
#10772  0x97f62b22 in -[__NSOperationInternal dealloc] ()
#10773  0x9104d5ef in -[NSObject release] ()
#10774  0x97f62ac8 in -[NSOperation dealloc] ()
#10775  0x9104d5ef in -[NSObject release] ()
#10776  0x99e41224 in CFRelease ()
#10777  0x99e56277 in -[__NSArrayM dealloc] ()
#10778  0x9104d5ef in -[NSObject release] ()
#10779  0x97f62b22 in -[__NSOperationInternal dealloc] ()
#10780  0x9104d5ef in -[NSObject release] ()
#10781  0x97f62ac8 in -[NSOperation dealloc] ()
#10782  0x9104d5ef in -[NSObject release] ()
#10783  0x99e41224 in CFRelease ()
#10784  0x99e56277 in -[__NSArrayM dealloc] ()
#10785  0x9104d5ef in -[NSObject release] ()
#10786  0x97f62b22 in -[__NSOperationInternal dealloc] ()
#10787  0x9104d5ef in -[NSObject release] ()
#10788  0x97f62ac8 in -[NSOperation dealloc] ()
#10789  0x9104d5ef in -[NSObject release] ()
#10790  0x99e41224 in CFRelease ()
#10791  0x99e56277 in -[__NSArrayM dealloc] ()
#10792  0x9104d5ef in -[NSObject release] ()
#10793  0x97f62b22 in -[__NSOperationInternal dealloc] ()
#10794  0x9104d5ef in -[NSObject release] ()
#10795  0x97f62ac8 in -[NSOperation dealloc] ()
#10796  0x9104d5ef in -[NSObject release] ()
#10797  0x99e41224 in CFRelease ()
#10798  0x99e56277 in -[__NSArrayM dealloc] ()
#10799  0x9104d5ef in -[NSObject release] ()
#10800  0x97f62b22 in -[__NSOperationInternal dealloc] ()
#10801  0x9104d5ef in -[NSObject release] ()
#10802  0x97f62ac8 in -[NSOperation dealloc] ()
#10803  0x9104d5ef in -[NSObject release] ()
#10804  0x99e41224 in CFRelease ()
#10805  0x99e56277 in -[__NSArrayM dealloc] ()
#10806  0x9104d5ef in -[NSObject release] ()
#10807  0x97f62b22 in -[__NSOperationInternal dealloc] ()
#10808  0x9104d5ef in -[NSObject release] ()
#10809  0x97f62ac8 in -[NSOperation dealloc] ()
#10810  0x9104d5ef in -[NSObject release] ()
#10811  0x99e41224 in CFRelease ()
#10812  0x99e56277 in -[__NSArrayM dealloc] ()
#10813  0x9104d5ef in -[NSObject release] ()
#10814  0x97f62b22 in -[__NSOperationInternal dealloc] ()
#10815  0x9104d5ef in -[NSObject release] ()
#10816  0x97f62ac8 in -[NSOperation dealloc] ()
#10817  0x9104d5ef in -[NSObject release] ()
#10818  0x99e41224 in CFRelease ()
#10819  0x99e56277 in -[__NSArrayM dealloc] ()
#10820  0x9104d5ef in -[NSObject release] ()
#10821  0x97f62b22 in -[__NSOperationInternal dealloc] ()
#10822  0x9104d5ef in -[NSObject release] ()
#10823  0x97f62ac8 in -[NSOperation dealloc] ()
#10824  0x9104d5ef in -[NSObject release] ()
#10825  0x99e41224 in CFRelease ()
#10826  0x99e56277 in -[__NSArrayM dealloc] ()
#10827  0x9104d5ef in -[NSObject release] ()
#10828  0x97f62b22 in -[__NSOperationInternal dealloc] ()
#10829  0x9104d5ef in -[NSObject release] ()
#10830  0x97f62ac8 in -[NSOperation dealloc] ()
#10831  0x9104d5ef in -[NSObject release] ()
#10832  0x99e41224 in CFRelease ()
#10833  0x99e56277 in -[__NSArrayM dealloc] ()
#10834  0x9104d5ef in -[NSObject release] ()
#10835  0x97f62b22 in -[__NSOperationInternal dealloc] ()
#10836  0x9104d5ef in -[NSObject release] ()
#10837  0x97f62ac8 in -[NSOperation dealloc] ()
#10838  0x9104d5ef in -[NSObject release] ()
#10839  0x99e41224 in CFRelease ()
#10840  0x99e56277 in -[__NSArrayM dealloc] ()
#10841  0x9104d5ef in -[NSObject release] ()
#10842  0x97f62b22 in -[__NSOperationInternal dealloc] ()
#10843  0x9104d5ef in -[NSObject release] ()
#10844  0x97f62ac8 in -[NSOperation dealloc] ()
#10845  0x9104d5ef in -[NSObject release] ()
#10846  0x99e41224 in CFRelease ()
#10847  0x99e56277 in -[__NSArrayM dealloc] ()
#10848  0x9104d5ef in -[NSObject release] ()
#10849  0x97f62b22 in -[__NSOperationInternal dealloc] ()
#10850  0x9104d5ef in -[NSObject release] ()
#10851  0x97f62ac8 in -[NSOperation dealloc] ()
#10852  0x9104d5ef in -[NSObject release] ()
#10853  0x99e41224 in CFRelease ()
#10854  0x99e56277 in -[__NSArrayM dealloc] ()
#10855  0x9104d5ef in -[NSObject release] ()
#10856  0x97f62b22 in -[__NSOperationInternal dealloc] ()
#10857  0x9104d5ef in -[NSObject release] ()
#10858  0x97f62ac8 in -[NSOperation dealloc] ()
#10859  0x9104d5ef in -[NSObject release] ()
#10860  0x99e41224 in CFRelease ()
#10861  0x99e56277 in -[__NSArrayM dealloc] ()
#10862  0x9104d5ef in -[NSObject release] ()
#10863  0x97f62b22 in -[__NSOperationInternal dealloc] ()
#10864  0x9104d5ef in -[NSObject release] ()
#10865  0x97f62ac8 in -[NSOperation dealloc] ()
#10866  0x9104d5ef in -[NSObject release] ()
#10867  0x99e41224 in CFRelease ()
#10868  0x99e56277 in -[__NSArrayM dealloc] ()
#10869  0x9104d5ef in -[NSObject release] ()
#10870  0x97f62b22 in -[__NSOperationInternal dealloc] ()
#10871  0x9104d5ef in -[NSObject release] ()
#10872  0x97f62ac8 in -[NSOperation dealloc] ()
#10873  0x9104d5ef in -[NSObject release] ()
#10874  0x99e41224 in CFRelease ()
#10875  0x99e56277 in -[__NSArrayM dealloc] ()
#10876  0x9104d5ef in -[NSObject release] ()
#10877  0x97f62b22 in -[__NSOperationInternal dealloc] ()
#10878  0x9104d5ef in -[NSObject release] ()
#10879  0x97f62ac8 in -[NSOperation dealloc] ()
#10880  0x9104d5ef in -[NSObject release] ()
#10881  0x99e41224 in CFRelease ()
#10882  0x99e56277 in -[__NSArrayM dealloc] ()
#10883  0x9104d5ef in -[NSObject release] ()
#10884  0x97f62b22 in -[__NSOperationInternal dealloc] ()
#10885  0x9104d5ef in -[NSObject release] ()
#10886  0x97f62ac8 in -[NSOperation dealloc] ()
#10887  0x9104d5ef in -[NSObject release] ()
#10888  0x99e41224 in CFRelease ()
#10889  0x99e56277 in -[__NSArrayM dealloc] ()
#10890  0x9104d5ef in -[NSObject release] ()
#10891  0x97f62b22 in -[__NSOperationInternal dealloc] ()
#10892  0x9104d5ef in -[NSObject release] ()
#10893  0x97f62ac8 in -[NSOperation dealloc] ()
#10894  0x9104d5ef in -[NSObject release] ()
#10895  0x99e41224 in CFRelease ()
#10896  0x99e56277 in -[__NSArrayM dealloc] ()
#10897  0x9104d5ef in -[NSObject release] ()
#10898  0x97f62b22 in -[__NSOperationInternal dealloc] ()
#10899  0x9104d5ef in -[NSObject release] ()
#10900  0x97f62ac8 in -[NSOperation dealloc] ()
#10901  0x9104d5ef in -[NSObject release] ()
#10902  0x99e41224 in CFRelease ()
#10903  0x99e56277 in -[__NSArrayM dealloc] ()
#10904  0x9104d5ef in -[NSObject release] ()
#10905  0x97f62b22 in -[__NSOperationInternal dealloc] ()
#10906  0x9104d5ef in -[NSObject release] ()
#10907  0x97f62ac8 in -[NSOperation dealloc] ()
#10908  0x9104d5ef in -[NSObject release] ()
#10909  0x99e41224 in CFRelease ()
#10910  0x99e56277 in -[__NSArrayM dealloc] ()
#10911  0x9104d5ef in -[NSObject release] ()
#10912  0x97f62b22 in -[__NSOperationInternal dealloc] ()
#10913  0x9104d5ef in -[NSObject release] ()
#10914  0x97f62ac8 in -[NSOperation dealloc] ()
#10915  0x9104d5ef in -[NSObject release] ()
#10916  0x97f49cca in __NSOQSchedule_f ()
#10917  0x9c1c9e21 in _dispatch_async_redirect_invoke ()
#10918  0x9c1c53a6 in _dispatch_client_callout ()
#10919  0x9c1c7467 in _dispatch_root_queue_drain ()
#10920  0x9c1c8732 in _dispatch_worker_thread2 ()
#10921  0x960c2dab in _pthread_wqthread ()

完整的崩溃上下文是(粗体表示崩溃行):

libobjc.A.dylib`objc::DenseMapBase<objc::DenseMap<objc_object*, unsigned long, true, objc::DenseMapInfo<objc_object*> >, objc_object*, unsigned long, objc::DenseMapInfo<objc_object*>, true>::find(objc_object* const&):
0x9104d800:  pushl  %ebp
0x9104d801:  movl   %esp, %ebp
0x9104d803:  pushl  %esi
0x9104d804:  subl   $20, %esp
0x9104d807:  leal   -8(%ebp), %eax
0x9104d80a:  movl   %eax, 8(%esp)
0x9104d80e:  movl   16(%ebp), %eax
0x9104d811:  movl   %eax, 4(%esp)
0x9104d815:  movl   12(%ebp), %esi
0x9104d818:  movl   %esi, (%esp)
**0x9104d81b:  calll  0x9104d9b6                ; bool objc::DenseMapBase<objc::DenseMap<objc_object*, unsigned long, true, objc::DenseMapInfo<objc_object*> >, objc_object*, unsigned long, objc::DenseMapInfo<objc_object*>, true>::LookupBucketFor<objc_object*>(objc_object* const&, std::__1::pair<objc_object*, unsigned long> const*&) const**
0x9104d820:  movl   12(%esi), %ecx
0x9104d823:  shll   $3, %ecx
0x9104d826:  addl   (%esi), %ecx
0x9104d828:  movl   8(%ebp), %edx
0x9104d82b:  testb  %al, %al
0x9104d82d:  je     0x9104d836                ; objc::DenseMapBase<objc::DenseMap<objc_object*, unsigned long, true, objc::DenseMapInfo<objc_object*> >, objc_object*, unsigned long, objc::DenseMapInfo<objc_object*>, true>::find(objc_object* const&) + 54
0x9104d82f:  movl   -8(%ebp), %eax
0x9104d832:  movl   %eax, (%edx)
0x9104d834:  jmp    0x9104d838                ; objc::DenseMapBase<objc::DenseMap<objc_object*, unsigned long, true, objc::DenseMapInfo<objc_object*> >, objc_object*, unsigned long, objc::DenseMapInfo<objc_object*>, true>::find(objc_object* const&) + 56
0x9104d836:  movl   %ecx, (%edx)
0x9104d838:  movl   %ecx, 4(%edx)
0x9104d83b:  addl   $20, %esp
0x9104d83e:  popl   %esi
0x9104d83f:  popl   %ebp
0x9104d840:  ret    $4
0x9104d843:  nop    

我尝试使用预先创建的队列,这没有区别。显然,由于依赖关系,这段代码是 XCode 5.0 32 位的问题。

编辑:事实上,我可以进一步隔离问题。XCOde 5.0 在 10.9 上的一个空的 Cocoa 应用程序项目在 ARC 和单个方法上会崩溃。如果它不在您的计算机上,请将 4269 增加到更大的值:

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    NSOperationQueue* aQueue = [[ NSOperationQueue alloc ] init ];
    NSMutableArray* array = [ NSMutableArray array ];
    for ( int i = 0; i < 4269; i++)
        [ array addObject: [ [NSOperation alloc ] init  ]];

    for ( int i = 1; i < [ array count ]; i++)
        [[ array objectAtIndex:i ] addDependency:[array objectAtIndex:i-1]];

    [ aQueue addOperations: array waitUntilFinished:NO ];
}

编辑2:

请注意,以下代码将在一个干净的新项目中崩溃(ARC ON,但我认为这无关紧要)。我希望队列保持强引用(保留)NSOperation。

  1. NSOperationQueue 被永久保存,永远不会被释放。
  2. 没有临时的 NSMutableArray。
  3. 操作一添加就开始运行

这是代码:

static NSOperationQueue* aQueue = nil;

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    aQueue = [[ NSOperationQueue alloc ] init ];
    NSOperation* lastOp = nil;
    for ( int i = 0; i < 5000 ; i++) {
        NSOperation* newOp = [ NSBlockOperation blockOperationWithBlock:^{ ;} ];
        if ( lastOp != nil )
            [ newOp addDependency: lastOp ];

        [ aQueue addOperation:newOp ];

        lastOp = newOp;
    }

}
4

6 回答 6

4

新理论

好的,这是关于发生了什么的另一种理论:

1)每个NSOperation对象都有一个指向所有依赖项的强指针,可能使用数组。

2)NSOperation释放引用dealloc,而不是在依赖操作完成时释放。

3) 结果,您得到一个引用链,阻止任何东西被释放,直到最后一个操作完成,它没有任何引用它。

4) 由于队列和数组是自动释放的,它们对NSOperation对象的引用消失了。

5)当最后一个操作完成时,它会释放一个字符串releasedealloc数组迭代调用,我在这里推测,会导致堆栈溢出。

我认为解决方案可能是NSOperation手动保留对对象的引用,并在它们全部完成后故意以相反的顺序(最后到第一个)释放它们。不是最优雅的解决方案,但如果我的理论是正确的,它应该可以工作。

于 2013-10-31T13:59:36.950 回答
3

基于 Daniel 和 Godel9 的分析,可以通过在执行时清理 NSOperation 依赖项来解决该问题:

@implementation MyOperation 

- (void) main 
{
  ...
  NSArray* dependencies = self.dependencies;
  for (NSOperation* op in dependencies)
    [self removeDependency:op];
}

@end

事实上,当一个操作执行时,它的依赖数组中的所有操作都完成了。不再需要在它们上保留指针。

于 2015-09-24T08:33:56.240 回答
1

看来 Godel9 是对的:当最后一个操作完成时,依赖项中的引用链会带来一连串的 dealloc(我知道但不知道这会导致问题)。如果该链中有足够多的对象,则会发生崩溃。为了确认这一点,我编写了一个带有自定义对象(Holder)的程序,该对象保留了另一个对象,该对象保留了另一个对象等......并且我自动释放所有对象。就释放/保留计数而言,这是完全有效的:除第一个之外的所有对象的保留计数都高于 1。在下一个自动释放周期中,第一个对象被自动释放,并且是唯一不被任何人引用的对象。它的释放触发了一系列的 dealloc。对于足够多的对象,这最终会崩溃,堆栈跟踪类似于我原来的问题。我很惊讶这会因 BAD_EXEC 故障而崩溃。我期待一些类似于 STACK_OVERFLOW 的东西(如果存在,我不知道)。

事后看来,这很明显(他们说事后看来是 20/20)。但是,我感谢 godel9 在 NSOperationQueue 中的依赖关系上下文中指出问题。

此外,如果对象从末尾释放,Godel9 提出的解决方案(保留一个包含所有对象引用的数组)将起作用,因为最后一个对象没有指向任何东西并且不会触发级联的 dealloc。

这是代码(基础工具项目)我不确定为什么计数需要这么高,但崩溃发生在相同的位置:

#import <Foundation/Foundation.h>

@interface Holder : NSObject

@property (strong) id object;
@property (assign) int i;

- (void) dealloc;
@end

@implementation Holder

- (void) dealloc
{
    [ _object release ];
    [ super dealloc ];
}

@end

int main(int argc, const char * argv[])
{
    @autoreleasepool {
        Holder* lastObject = nil;

        for ( int i = 0; i < 1000000; i++) {
            Holder* anObject = [[[ Holder alloc ] init] autorelease ];

            if ( lastObject != nil )
                lastObject.object = anObject;

            lastObject = anObject;
        }
    }

}
于 2013-11-01T02:55:58.090 回答
1

几年过去了......所以我不知道是否有人需要解决方案。崩溃是由级联释放的堆栈溢出引起的。所以解决办法之一就是及时打破这个版本。

@implementation SafeOperation

- (void)dealloc {
    __block NSArray<NSOperation *> *dependencies = nil;

    @autoreleasepool {
        dependencies = self.dependencies;
        if ([dependencies count] == 0) {
            return;
        }

        for (NSOperation *op in dependencies) {
            [self removeDependency:op];
        }
    }

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
         dependencies = nil;
    });
}

@end
于 2017-09-04T16:07:22.493 回答
0

您的数组正在从您下方释放。如果对数组的引用超出了方法的范围(一直到 10,000),我运行您的示例没有问题。这也解释了为什么如果您设置waitUntilFinished:YES.

这并不总是以较低的数字崩溃的原因是数组占用的内存尚未重新分配给其他东西。

此外,NSOperation 是一个抽象类;你不应该实例化它。

这是对不会崩溃的代码的修改(需要 ARC)

static NSMutableArray* array;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    NSOperationQueue* aQueue = [[ NSOperationQueue alloc ] init ];
    aQueue.maxConcurrentOperationCount = 1;
    array = [ NSMutableArray arrayWithCapacity:10000];

    @autoreleasepool {
        for ( int i = 0; i < 10000; i++)
            [ array addObject: [NSBlockOperation blockOperationWithBlock:(void (^)(void))^{
                NSLog(@"executing %d", i);
            }]];
    }
    for ( int i = 1; i < [ array count ]; i++)
        [[ array objectAtIndex:i ] addDependency:[array objectAtIndex:i-1]];

    [ aQueue addOperations: array waitUntilFinished:NO ];
}

据我所知,您只是试图保证您的操作的串行执行。为什么不做aQueue.maxConcurrentOperationCount = 1;呢?

于 2013-10-31T15:33:45.237 回答
0

你在孩子之前移除父母,你会崩溃。

在叶子知道(但不保留,而不是绕圈子)父母的树状结构中很常见。

在这里看不到错误

于 2013-10-31T16:48:20.983 回答