NSOperationQueue bug with dependencies - objective-c

I am using NSOperation and NSOperationQueue for performing a sequence of operations, all dependent on each other (2 on 1, 3 on 2, etc...). I set the dependency after I create the operations. I am encountering problems when the queue completes: the program crashes in the _release part of the code, apparently when the NSOperations are getting released. Note that they all get released at the end by the queue, because it is only after the very last one which depends on the second last one, which depends on etc... that they can be released. If I remove any dependency, the code runs fine. If I change waitUntilFinished: to NO, it crashes, if it is YES, it does not.
I have isolated the problem to the following code which does not use any of my custom classes. NSOperation by default is a class that does absolutely nothing. Yet, this still crashes when all operations have completed. Therefore, it appears I am not using NSOperationQueue properly but can't see what is wrong. I am running on 10.9 and I have noticed that in general Maverick 10.9 is much more sensitive to these issues than 10.8.
I call this method from the main Thread with a Menu item:
- (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
}
This will crash every single time with:
bool objc::DenseMapBase >, objc_object*, unsigned long, objc::DenseMapInfo, true>: (EXC_BAD_ACCESS)
The full stack is:
#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 ()
The full crash context is (bold for crash line):
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
I tried using a pre-created queue, this makes no difference. Apparently, with dependencies, this code is a problem with XCode 5.0, 32-bit.
Edit: In fact, I can isolate the problem much further. An empty Cocoa Application project in XCOde 5.0 on 10.9 with ARC on and a single method will crash. If it does not on your computer,
increase 4269 to anything bigger:
- (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 ];
}
Edit 2:
Please note that the following code will crash in a clean new project (with ARC ON, but I think this is irrelevant). I expect the queue to keep a strong reference (retain) the NSOperation.
the NSOperationQueue is kept forever, is never released.
there is no temporary NSMutableArray.
The operations start running as soon as they are added
Here is the code:
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;
}
}

New Theory
Okay, here's another theory as to what's going on:
1) Each NSOperation object keeps a strong pointer to all dependencies, probably using an array.
2) NSOperation releases the reference in dealloc, not when the dependent operation is complete.
3) As a result, you get a chain of references that prevents anything from being deallocated until the last operation completes, which does not have anything referencing it.
4) Since the queue and array are auto released, their references to the NSOperation objects go away.
5) When the last operation completes, it unleashes a string of release, dealloc, array iteration calls that, and I'm speculating here, cause a stack overflow.
I think the solution might be to keep references to the NSOperation objects manually and deliberately release them in reverse order (last to first) after they're all completed. Not really the most elegant solution, but if my theory is right, it should work.

Building on the analysis made by Daniel and Godel9, one may solve the issue by cleaning up the NSOperation dependencies while it executes:
#implementation MyOperation
- (void) main
{
...
NSArray* dependencies = self.dependencies;
for (NSOperation* op in dependencies)
[self removeDependency:op];
}
#end
Indeed, when an operation executes, all operations in its dependencies array are finished. It is not required to retain a pointer on them anymore.

It appears that Godel9 is right: the chain of references in the dependencies bring a cascade of dealloc's when the last operation completes (which I knew but did not know could cause a problem). With a sufficiently large number of objects in that chain, there is a crash. To confirm that, I wrote a program with a custom object (Holder) that retains another object that retains another etc... and I autorelease all objects. In terms of release/retain count, this is perfectly valid: all objects except the first one have a retain count higher than 1. On the next autorelease cycle, the first object is autoreleased and is the only one to not be referenced by anyone. Its release triggers a cascade of dealloc's. With a sufficiently large number of objects, this eventually crashes with a stack trace similar to my original question. I was very surprised that this crashed with a BAD_EXEC fault. I expected something along the lines of STACK_OVERFLOW (if that exists, I don't know).
This is quite obvious in hindsight (hindsight is 20/20 they say). However, I thank godel9 for pointing the issue in the context of dependencies in NSOperationQueue.
Also, the solution proposed by Godel9 (keep an array with references to all objects) will work if the object are released from the end since the very last one is not pointing to anything and will not trigger a cascade of dealloc's.
Here is the code (Foundation Tool project) I am not sure why the count needs to be so high, but the crash occurs at identical spots:
#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;
}
}
}

Several years passed ... so I don't know if anyone needs the solution.
The crash is caused by stack overflow of cascade release. So one of the solutions is to break this release in time.
#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

your array is being deallocated from under you. I have no problem running your sample if the reference to the array is outside the scope of the method (all the way up to 10,000). That also explains why your code runs fine for you if you set waitUntilFinished:YES.
the reason why this doesn't always crash with lower numbers is because the memory that the array occupied has not yet been reallocated to something else.
Additionally, NSOperation is an abstract class; you shouldn't be instantiating it.
here is a modification to your code that doesn't crash (requires 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 ];
}
From what I can tell you are simply trying to guarantee serial execution for your operations. why not just do aQueue.maxConcurrentOperationCount = 1;?

you remove the parent before the children and you get a crash.
Quite common with tree like structures where the leafs know (but not retain, than you'd go in circles) the parent.
don't see a bug here

Related

objc_msgSend crash Objective-C

I got crash report from live user
I have NSObject which has nsstring
#interface MountedVolume : NSObject
#property (nonatomic, strong) NSString *name;
#end
View controller has textfield it values gets changed when notification
received .
#interface ViewController : NSViewController {
MountedVolume *selectedVolume;
__weak IBOutlet NSTextField *txtVolumeName;
}
#end
#implementation ViewController
- (void)viewDidLoad {
[[NSNotificationCenter defaultCenter] addObserverForName:DCNotificationNameVolumesUpdated object:nil queue:nil usingBlock:^(NSNotification * _Nonnull note) {
dispatch_async(dispatch_get_main_queue(), ^{
//crash report says in this line it got crashed
txtVolumeName.stringValue = selectedVolume.name;
});
}];
}
#end
Below is the crash report any suggestion how to deal with this?
crash report
Crashed: com.apple.main-thread
0 libobjc.A.dylib 0x7fff6ac2639d objc_msgSend + 29
1 AppKit 0x7fff3db3d868 -[NSCell _objectValue:forString:errorDescription:] + 157
2 AppKit 0x7fff3db3d71d -[NSCell setStringValue:] + 40
3 AppKit 0x7fff3db95044 -[NSControl setStringValue:] + 135
4 MyApp 0x104de865b __40-[ViewController viewDidLoad]_block_invoke_3 (ViewController.m:172)
5 libdispatch.dylib 0x7fff6c3ab5f8 _dispatch_call_block_and_release + 12
6 libdispatch.dylib 0x7fff6c3ac63d _dispatch_client_callout + 8
7 libdispatch.dylib 0x7fff6c3b768d _dispatch_main_queue_callback_4CF + 1135
8 CoreFoundation 0x7fff40435f56 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9
9 CoreFoundation 0x7fff40435683 __CFRunLoopRun + 2300
10 CoreFoundation 0x7fff40434b35 CFRunLoopRunSpecific + 459
11 HIToolbox 0x7fff3f71396b RunCurrentEventLoopInMode + 292
12 HIToolbox 0x7fff3f7136a5 ReceiveNextEventCommon + 603
13 HIToolbox 0x7fff3f713436 _BlockUntilNextEventMatchingListInModeWithFilter + 64
14 AppKit 0x7fff3daad987 _DPSNextEvent + 965
15 AppKit 0x7fff3daac71f -[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 1361
16 AppKit 0x7fff3daa683c -[NSApplication run] + 699
17 AppKit 0x7fff3da95d7c NSApplicationMain + 777
18 libdyld.dylib 0x7fff6c3f93d5 start + 1
Looking at the docs, stringValue does not appear to be optional. You do not initialize selectedVolume before viewDidLoad (as far as I can tell) and that means you are likely trying to set this value to nil inside this notification block if it runs before selectedVolume is assigned a value. I would start by trying to set txtVolumeName.stringValue to a hard-coded value first and see if it stops crashing altogether. If it does, you may need to guard against nil values before you call the setter.
e.g.
NSString *string;
NSTextField *textField = [[NSTextField alloc]init];
if (string) {
textField.stringValue = string;
}

Get web text to Label

I need to get the text from URL http://cast.midiaip.com.br:6530/currentsong?sid=1 and display it in a UILabel
My code is like that:
ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
#property (strong, nonatomic) IBOutlet UILabel *musicasLabel;
- (IBAction)textoButton:(id)sender;
#property (strong, nonatomic) IBOutlet UIWebView *webView;
#end
ViewController.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize musicasLabel;
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)textoButton:(id)sender {
NSURL *url = [NSURL URLWithString:#"http://cast.midiaip.com.br:6530/currentsong?sid=1"];
NSData *data = [NSData dataWithContentsOfURL:url];
NSString *string = [NSString stringWithUTF8String:[data bytes]];
musicasLabel.text = string;
}
#end
I always get the error:
2015-04-17 02:55:21.637 teste label[14194:797672] ***
Terminating app due to uncaught exception
'NSInvalidArgumentException', reason: '***
+[NSString stringWithUTF8String:]: NULL cString'
*** First throw call stack:
(
0 CoreFoundation 0x000000010cf1bf35
__exceptionPreprocess + 165
1 libobjc.A.dylib 0x000000010cbb4bb7 objc_exception_throw + 45
2 CoreFoundation 0x000000010cf1be6d +[NSException raise:format:] + 205
3 Foundation 0x000000010c719464 +[NSString stringWithUTF8String:] + 78
4 teste label 0x000000010c6885e5 -[ViewController textoButton:] + 181
5 UIKit 0x000000010d3098be -[UIApplication sendAction:to:from:forEvent:] + 75
6 UIKit 0x000000010d410410 -[UIControl _sendActionsForEvents:withEvent:] + 467
7 UIKit 0x000000010d40f7df -[UIControl touchesEnded:withEvent:] + 522
8 UIKit 0x000000010d34f308 -[UIWindow _sendTouchesForEvent:] + 735
9 UIKit 0x000000010d34fc33 -[UIWindow sendEvent:] + 683
10 UIKit 0x000000010d31c9b1 -[UIApplication sendEvent:] + 246
11 UIKit 0x000000010d329a7d _UIApplicationHandleEventFromQueueEvent + 17370
12 UIKit 0x000000010d305103 _UIApplicationHandleEventQueue + 1961
13 CoreFoundation 0x000000010ce51551 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
14 CoreFoundation 0x000000010ce4741d __CFRunLoopDoSources0 + 269
15 CoreFoundation 0x000000010ce46a54 __CFRunLoopRun + 868
16 CoreFoundation 0x000000010ce46486 CFRunLoopRunSpecific + 470
17 GraphicsServices 0x00000001104ea9f0 GSEventRunModal + 161
18 UIKit 0x000000010d308420 UIApplicationMain + 1282
19 teste label 0x000000010c688ae3 main + 115
20 libdyld.dylib 0x000000010f4ab145 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)
Thank you very much!!!
You are initializing your string incorrectly. Your question is answered here:
convert UTF-8 encoded NSData to a NSString

iOS exception in pushViewController

I'm trying to create an NSMutableArray of ModuleViewControllers (which inherits from UIViewController) in order to open a given view from a given button. The ModuleViewController is also described in ModuleViewController.xib
So I load a list of module xml files and pass them, one by one, to a constructor (which ignores them atm) and then add the result to an NSMutableArray.
The problem happens when I try to push the view controller. I get a SIGABRT/exception and I'm not sure why. Any ideas?
Failed Call:
-(IBAction) buttonPressed:(id)sender {
ModuleViewController *module = [moduleVCList objectAtIndex:[sender tag]];
[[self navigationController] pushViewController:module animated:YES];
}
Constructor Call:
[moduleVCList addObject:
[[ModuleViewController alloc] initWithXMLName:[module objectForKey:#"file"]]];
Constructor:
- (id)initWithXMLName:(NSString *)xmlName {
self = [super initWithNibName:#"ModuleViewController" bundle:nil];
if (self) {
}
return self;
}
Backtrace:
#0 0x01867cf0 in objc_exception_throw ()
#1 0x0167ea78 in +[NSException raise:format:arguments:] ()
#2 0x0167e9e9 in +[NSException raise:format:] ()
#3 0x00209f0d in -[UIViewController _loadViewFromNibNamed:bundle:] ()
#4 0x0020a3a9 in -[UIViewController loadView] ()
#5 0x0020a5cb in -[UIViewController view] ()
#6 0x0020a941 in -[UIViewController contentScrollView] ()
#7 0x0021c47d in -[UINavigationController _computeAndApplyScrollContentInsetDeltaForViewController:] ()
#8 0x0021c66f in -[UINavigationController _layoutViewController:] ()
#9 0x0021c93b in -[UINavigationController _startTransition:fromViewController:toViewController:] ()
#10 0x0021d3df in -[UINavigationController _startDeferredTransitionIfNeeded] ()
#11 0x0021d986 in -[UINavigationController pushViewController:transition:forceImmediate:] ()
#12 0x0021d5a4 in -[UINavigationController pushViewController:animated:] ()
#13 0x00003c1a in -[MainViewController buttonPressed:] (self=0x6a283d0, _cmd=0xb874, sender=0x6a286c0) at *snip*/MainViewController.m:149
#14 0x016d7ec9 in -[NSObject performSelector:withObject:withObject:] ()
#15 0x001475c2 in -[UIApplication sendAction:to:from:forEvent:] ()
#16 0x0014755a in -[UIApplication sendAction:toTarget:fromSender:forEvent:] ()
#17 0x001ecb76 in -[UIControl sendAction:to:forEvent:] ()
#18 0x001ed03f in -[UIControl(Internal) _sendActionsForEvents:withEvent:] ()
#19 0x001ec2fe in -[UIControl touchesEnded:withEvent:] ()
#20 0x0016ca30 in -[UIWindow _sendTouchesForEvent:] ()
#21 0x0016cc56 in -[UIWindow sendEvent:] ()
#22 0x00153384 in -[UIApplication sendEvent:] ()
#23 0x00146aa9 in _UIApplicationHandleEvent ()
#24 0x015c0fa9 in PurpleEventCallback ()
#25 0x016aa1c5 in __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ ()
#26 0x0160f022 in __CFRunLoopDoSource1 ()
#27 0x0160d90a in __CFRunLoopRun ()
#28 0x0160cdb4 in CFRunLoopRunSpecific ()
#29 0x0160cccb in CFRunLoopRunInMode ()
#30 0x015bf879 in GSEventRunModal ()
#31 0x015bf93e in GSEventRun ()
#32 0x00144a9b in UIApplicationMain ()
#33 0x00002862 in main (argc=1, argv=0xbfffedc8) at *snip*/main.m:16
#34 0x000027d5 in start ()

UIPickerView&ActionSheet [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 11 years ago.
I try to make a PickerView with ActionSheet.The code is ok in X-code, but crash will occur when I run it and press the "Button", please help to check what have I missed?
Thank you.
Here is the .h file
#import <UIKit/UIKit.h>
#interface UIPickerView_ActionSheetViewController : UIViewController <UIActionSheetDelegate, UIPickerViewDelegate>
{
IBOutlet UIButton *button;
}
#property (nonatomic, retain) UIButton *button;
- (IBAction)buttonPressed;
#end
Here is the .m file
#import "UIPickerView_ActionSheetViewController.h"
#implementation UIPickerView_ActionSheetViewController
#synthesize button;
- (IBAction)buttonPressed
{
UIActionSheet *menu = [[UIActionSheet alloc] initWithTitle:#"currentData"
delegate:self
cancelButtonTitle:#"Done"
destructiveButtonTitle:#"Cancel"
otherButtonTitles:nil];
UIPickerView *pickerView = [[UIPickerView alloc]initWithFrame:CGRectMake(0,40,480,200)];
pickerView.delegate = self;
pickerView.showsSelectionIndicator = YES;
[menu addSubview:pickerView];
[menu showInView:self.view];
[menu setBounds:CGRectMake(0,0,480, 320)];
[pickerView release];
[menu release];
}
- (void)dealloc
{
[button release];
[super dealloc];
}
- (void)didReceiveMemoryWarning
{
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload
{
self.button=nil;
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#end
Crash on int retVal = UIApplicationMain(argc, argv, nil, nil);
#import <UIKit/UIKit.h>
int main(int argc, char *argv[])
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
int retVal = UIApplicationMain(argc, argv, nil, nil);
[pool release];
return retVal;
}
Crash Info
#0 0x9631817a in __kill ()
#1 0x9631816c in kill$UNIX2003 ()
#2 0x963aa879 in raise ()
#3 0x963c09b8 in abort ()
#4 0x9619dfda in __gnu_cxx::__verbose_terminate_handler ()
#5 0x00f1c23b in _objc_terminate ()
#6 0x9619c17a in __cxxabiv1::__terminate ()
#7 0x9619c1ba in std::terminate ()
#8 0x9619c2b8 in __cxa_throw ()
#9 0x00f1c416 in objc_exception_throw ()
#10 0x00dca0bb in -[NSObject(NSObject) doesNotRecognizeSelector:] ()
#11 0x00d39966 in ___forwarding___ ()
#12 0x00d39522 in __forwarding_prep_0___ ()
#13 0x0001a4fd in -[UIApplication sendAction:to:from:forEvent:] ()
#14 0x000aa799 in -[UIControl sendAction:to:forEvent:] ()
#15 0x000acc2b in -[UIControl(Internal) _sendActionsForEvents:withEvent:] ()
#16 0x000ab7d8 in -[UIControl touchesEnded:withEvent:] ()
#17 0x0003eded in -[UIWindow _sendTouchesForEvent:] ()
#18 0x0001fc37 in -[UIApplication sendEvent:] ()
#19 0x00024f2e in _UIApplicationHandleEvent ()
#20 0x01001992 in PurpleEventCallback ()
#21 0x00da9944 in __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ ()
#22 0x00d09cf7 in __CFRunLoopDoSource1 ()
#23 0x00d06f83 in __CFRunLoopRun ()
#24 0x00d06840 in CFRunLoopRunSpecific ()
#25 0x00d06761 in CFRunLoopRunInMode ()
#26 0x010001c4 in GSEventRunModal ()
#27 0x01000289 in GSEventRun ()
#28 0x00028c93 in UIApplicationMain ()
#29 0x00001c09 in main (argc=1, argv=0xbfffef8c) at main.m:14
Maybe this can help more
Attaching to process 606.
2011-12-10 06:37:08.456 UIPickerView_ActionSheet[606:207] -[UIPickerView_ActionSheetViewController DatePickerView]: unrecognized selector sent to instance 0x602dfb0
2011-12-10 06:37:08.458 UIPickerView_ActionSheet[606:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIPickerView_ActionSheetViewController DatePickerView]: unrecognized selector sent to instance 0x602dfb0'
*** Call stack at first throw:
(
0 CoreFoundation 0x00dc85a9 __exceptionPreprocess + 185
1 libobjc.A.dylib 0x00f1c313 objc_exception_throw + 44
2 CoreFoundation 0x00dca0bb -[NSObject(NSObject) doesNotRecognizeSelector:] + 187
3 CoreFoundation 0x00d39966 ___forwarding___ + 966
4 CoreFoundation 0x00d39522 _CF_forwarding_prep_0 + 50
5 UIKit 0x0001a4fd -[UIApplication sendAction:to:from:forEvent:] + 119
6 UIKit 0x000aa799 -[UIControl sendAction:to:forEvent:] + 67
7 UIKit 0x000acc2b -[UIControl(Internal) _sendActionsForEvents:withEvent:] + 527
8 UIKit 0x000ab7d8 -[UIControl touchesEnded:withEvent:] + 458
9 UIKit 0x0003eded -[UIWindow _sendTouchesForEvent:] + 567
10 UIKit 0x0001fc37 -[UIApplication sendEvent:] + 447
11 UIKit 0x00024f2e _UIApplicationHandleEvent + 7576
12 GraphicsServices 0x01001992 PurpleEventCallback + 1550
13 CoreFoundation 0x00da9944 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 52
14 CoreFoundation 0x00d09cf7 __CFRunLoopDoSource1 + 215
15 CoreFoundation 0x00d06f83 __CFRunLoopRun + 979
16 CoreFoundation 0x00d06840 CFRunLoopRunSpecific + 208
17 CoreFoundation 0x00d06761 CFRunLoopRunInMode + 97
18 GraphicsServices 0x010001c4 GSEventRunModal + 217
19 GraphicsServices 0x01000289 GSEventRun + 115
20 UIKit 0x00028c93 UIApplicationMain + 1160
21 UIPickerView_ActionSheet 0x00001cf9 main + 121
22 UIPickerView_ActionSheet 0x00001c75 start + 53
)
terminate called after throwing an instance of 'NSException'
Current language: auto; currently objective-c
[UIPickerView_ActionSheetViewController DatePickerView]: unrecognized selector sent to instance 0x602dfb0
What this tells you is that somewhere you are sending the message DatePickerView to your view controller instance, and it doesn't recognise it.
I can't see such a call anywhere in the code above so it is either in a different file in your project, or you have an old or renamed outlet connection in interface builder. If you have copied this code or some of the resources from somewhere else then you will need to update them to match your actual requirements.

Why does my app crash

I made a class. This is the h file.
// MyClass.h
#import <Foundation/Foundation.h>
#interface MyClass : NSObject <NSCoding> {
NSString *string1;
NSString *string2;
}
#property (nonatomic, retain) NSString *string1;
#property (nonatomic, retain) NSString *string2;
#end
This is the m file
// MyClass.m
#import "MyClass.h"
#implementation MyClass
#synthesize string1, string2;
- (void)encodeWithCoder:(NSCoder *)coder;
{
NSLog(#"encodeWithCoder");
[coder encodeObject:string1 forKey:#"string1"];
[coder encodeObject:string2 forKey:#"string2"];
}
- (id)initWithCoder:(NSCoder *)coder;
{
NSLog(#"initWithCoder");
self = [super init];
self.string1 = [coder decodeObjectForKey:#"string1"];
self.string2 = [coder decodeObjectForKey:#"string2"];
return self;
}
- (void)dealloc {
[string1 release];
[string2 release];
[super dealloc];
}
#end
I created an array of these objects like this
MyClass *object1 = [[MyClass alloc] init];
object1.string1 = #"object1 string1";
object1.string2 = #"string1 string2";
MyClass *object2 = [[MyClass alloc] init];
object2.string1 = #"object2 string1";
object2.string2 = #"object2 string2";
theArray = [[NSMutableArray alloc] initWithObjects:object1, object2, nil];
Then I saved the array like this
[[NSUserDefaults standardUserDefaults] setObject:[NSKeyedArchiver archivedDataWithRootObject:theArray] forKey:#"savedArray"];
Then I loaded the array from disk like this.
NSData *theData = [[NSUserDefaults standardUserDefaults] objectForKey:#"savedArray"];
if (theData != nil) {
NSLog(#"found something");
theArray = [NSMutableArray arrayWithArray:[NSKeyedUnarchiver unarchiveObjectWithData:theData]];
}
The program runs normally without error until it gets to this
DetailViewController *detailViewController = [[DetailViewController alloc] initWithNibName:#"DetailViewController" bundle:nil];
// ...
// Pass the selected object to the new view controller.
detailViewController.myObject = [theArray objectAtIndex:indexPath.row];
It crashes on that last line. It only crashes if I load the array using NSUserDefaults, however I don't notice anything I did wrong with that part.
When it crashes this is what the debugger says
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSCFString objectAtIndex:]: unrecognized selector sent to instance 0x5955e50'
*** Call stack at first throw:
(
0 CoreFoundation 0x02395919 __exceptionPreprocess + 185
1 libobjc.A.dylib 0x024e35de objc_exception_throw + 47
2 CoreFoundation 0x0239742b -[NSObject(NSObject) doesNotRecognizeSelector:] + 187
3 CoreFoundation 0x02307116 ___forwarding___ + 966
4 CoreFoundation 0x02306cd2 _CF_forwarding_prep_0 + 50
5 custom object array save test 0x00002872 -[RootViewController tableView:didSelectRowAtIndexPath:] + 156
6 UIKit 0x0032b718 -[UITableView _selectRowAtIndexPath:animated:scrollPosition:notifyDelegate:] + 1140
7 UIKit 0x00321ffe -[UITableView _userSelectRowAtIndexPath:] + 219
8 Foundation 0x00038cea __NSFireDelayedPerform + 441
9 CoreFoundation 0x02376d43 __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 19
10 CoreFoundation 0x02378384 __CFRunLoopDoTimer + 1364
11 CoreFoundation 0x022d4d09 __CFRunLoopRun + 1817
12 CoreFoundation 0x022d4280 CFRunLoopRunSpecific + 208
13 CoreFoundation 0x022d41a1 CFRunLoopRunInMode + 97
14 GraphicsServices 0x02bfa2c8 GSEventRunModal + 217
15 GraphicsServices 0x02bfa38d GSEventRun + 115
16 UIKit 0x002c7b58 UIApplicationMain + 1160
17 custom object array save test 0x00002160 main + 102
18 custom object array save test 0x000020f1 start + 53
19 ??? 0x00000001 0x0 + 1
)
terminate called after throwing an instance of 'NSException'
Edit:
I was able to fix the problem by replacing this line
theArray = [NSMutableArray arrayWithArray:[NSKeyedUnarchiver unarchiveObjectWithData:theData]];
with this liine
theArray = [[NSMutableArray alloc] initWithArray:[NSKeyedUnarchiver unarchiveObjectWithData:theData]];
so I guess the question now is why did that solve the problem?
I don't see anything wrong with your archiving/unarchiving code. I suspect that indexPath.row is out of range.
EDIT after OP edited question:
The error message says: -[NSCFString objectAtIndex:]: unrecognized selector sent to instance 0x5955e50
You'll notice that this means that 'theArray' is actually pointing at an NSString. Somewhere you have assigned the wrong thing to your 'theArray' variable.
EDIT again after another OP edit:
In your original code you had been using alloc/initWithArray: instead of arrayWithArray:.
The arrayWithArray: usage didn't work for you because that method returns an autoreleased object. So by the time you used it later that reference could have been pointing at just about anything, and hence in one case it happened to be pointing at a string.