NSOperationQueue与依赖项的错误

时间:2013-10-30 20:22:17

标签: objective-c nsoperationqueue

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

我已将问题隔离到以下代码,该代码不使用任何自定义类。默认情况下,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&gt;,objc_object *,unsigned long,objc :: DenseMapInfo,true&gt; :( 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中的空Cocoa应用程序项目在10.9上使用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. 操作一旦添加就开始运行
  4. 以下是代码:

    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;
        }
    
    }
    

6 个答案:

答案 0 :(得分:3)

新理论

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

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

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

3)因此,您将获得一系列引用,这些引用可以防止在最后一个操作完成之前释放任何内容,而该操作没有任何引用它的内容。

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

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

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

答案 1 :(得分:2)

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

@implementation MyOperation 

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

@end

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

答案 2 :(得分:1)

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

事后看来这很明显(后见之明他们说的是20/20)。但是,我感谢godel9将问题指向NSOperationQueue中的依赖关系。

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

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

#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;
        }
    }

}

答案 3 :(得分: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;

答案 4 :(得分:0)

你在孩子面前删除了父母,然后你就崩溃了。

与树状结构相当常见,其中叶子知道(但不保留,而不是留在圆圈中)父母。

在这里看不到错误

答案 5 :(得分:0)

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

@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