PDA

View Full Version : Am I using NSOperationQueue wrong here??




dantastic
Jan 30, 2011, 03:06 PM
Newbe here.
I think I've found the root cause but I don't understand why this is a problem and I was hoping someone could point me to additional ways of troubleshooting this type of issue.





else if (sender == faceButton) {
NSNumber *ops = [NSNumber numberWithUnsignedInteger:[myNSOperationQueue operationCount]];
[myNSOperationQueue cancelAllOperations];
if ( [ops intValue] == 0){
AnimateButton *fadeButton = [[AnimateButton alloc] initWithButton:sender controller:self];
[myNSOperationQueue addOperation:fadeButton];
[fadeButton release];
}
[ops release];
}


This piece of code will cause a EXEC_BAD_ACCESS after a few rapid clicks of the button.

If I don't check the queue but use the following:

else if (sender == faceButton) {
[myNSOperationQueue cancelAllOperations];
AnimateButton *fadeButton = [[AnimateButton alloc] initWithButton:sender controller:self];
[myNSOperationQueue addOperation:fadeButton];
[fadeButton release];


Everything is working fine. (I'll create an extra unnecessary object that will be killed immediately, but...)

What's strange though is that I get a

*** -[CFNumber _getValue:forType:]: message sent to deallocated instance 0x4b1b840


If I click my way slowly through the interface generally on the 6th click the app crashes. If I'm really fast I can crash the app the 3rd time the button is pressed.

I initially tried to return the malloc history for that object:

(gdb) info malloc-history 0x4b1b840
Alloc: Block address: 0x04b1b840 length: 16
Stack - pthread: 0xa0078540 number of frames: 19
0: 0x90c0b1dc in malloc_zone_malloc
1: 0xcbb80d in _CFRuntimeCreateInstance
2: 0xcd87c3 in CFNumberCreate
3: 0xce95e9 in __CFBinaryPlistCreateObject2
4: 0xce8e82 in __CFBinaryPlistCreateObject2
5: 0xce86a6 in __CFBinaryPlistCreateObject2
6: 0xcdea29 in __CFTryParseBinaryPlist
7: 0xcde468 in _CFPropertyListCreateWithData
8: 0xcde3da in CFPropertyListCreateWithData
9: 0xcde36f in CFPropertyListCreateFromXMLData
10: 0xcd056c in _CFBundleCopyInfoDictionaryInDirectoryWithVersion
11: 0xcd025f in CFBundleGetInfoDictionary
12: 0xcc3ede in _CFBundleCreate
13: 0xcbf147 in _CFBundleGetMainBundleAlreadyLocked
14: 0xcbf088 in CFBundleGetMainBundle
15: 0x15df8 in +[NSBundle mainBundle]
16: 0x2c30f1 in UIApplicationMain
17: 0x20d0 in main at /Users/user/Documents/Apps/switchImage/main.m:14
18: 0x2061 in start
kill


But that didn't make me any wiser so I went ahead and added a
NSLog(@"myClass init %p", self);
To every one of my classes and it seems like whatever was at 0x4b1b840 was not one of my objects...

Can someone please help me understand exactly what in the above makes my app crash?



chown33
Jan 30, 2011, 03:25 PM
First, why are you using an NSNumber at all?

The operationCount method returns a simple integer, does it not?

Since all you're doing is comparing the integer value to 0, exactly what purpose does wrapping the integer into an NSNumber serve?

If you don't know the answer to the last question, then you don't understand the difference between an integer and an NSNumber, and you should review the fundamentals.


Second, who owns the NSNumber reference in the variable ops?

Based on its ownership, should you be releasing it (the [ops release] line)?

If you don't understand ownership, you need to review the Memory Management Guide:
http://developer.apple.com/library/ios/#documentation/cocoa/Conceptual/MemoryMgmt/MemoryMgmt.html

dantastic
Jan 31, 2011, 03:17 AM
First, why are you using an NSNumber at all?

The operationCount method returns a simple integer, does it not?


I think you're spot on. When I first wrote the piece I couldn't get the operationCount to cast to an int but I've tried again now and done a

NSInteger opp = [myNSOperationQueue operationCount];

And it cast no problem so I think I was caught by the NSInteger/int use.


If you don't understand ownership, you need to review the Memory Management Guide:
http://developer.apple.com/library/ios/#documentation/cocoa/Conceptual/MemoryMgmt/MemoryMgmt.html

Yup, this should be one of my next stops...

thanks!