I'm currently using TestFlight in order to get remote crash reports on a beta version of our app. I've received a stack trace, however I'm not quite sure how to narrow down the problem. Here's the report I've received:
0 Holler 0x0003f2a1 Holler + 254625
1 Holler 0x0003f6b7 Holler + 255671
2 libsystem_c.dylib 0x344da72f _sigtramp + 42
3 AppSupport 0x34dfc58d CPRecordCopyProperty + 12
4 AddressBook 0x33e333bf ABRecordCopyValue + 14
5 Holler 0x00018df5 Holler + 97781
6 Holler 0x000182d3 Holler + 94931
7 Holler 0x0000a561 Holler + 38241
8 Holler 0x00033e0f Holler + 208399
9 CoreFoundation 0x3675d571 -[NSObject(NSObject) performSelector:withObject:withObject:] + 24
10 UIKit 0x355efec9 -[UIApplication sendAction:to:from:forEvent:] + 84
11 UIKit 0x355efe69 -[UIApplication sendAction:toTarget:fromSender:forEvent:] + 32
12 UIKit 0x355efe3b -[UIControl sendAction:to:forEvent:] + 38
13 UIKit 0x355efb8d -[UIControl(Internal) _sendActionsForEvents:withEvent:] + 356
14 UIKit 0x355f0423 -[UIControl touchesEnded:withEvent:] + 342
15 UIKit 0x355eebf5 -[UIWindow _sendTouchesForEvent:] + 368
16 UIKit 0x355ee56f -[UIWindow sendEvent:] + 262
17 UIKit 0x355d7313 -[UIApplication sendEvent:] + 298
18 UIKit 0x355d6c53 _UIApplicationHandleEvent + 5090
19 GraphicsServices 0x35f11e77 PurpleEventCallback + 666
20 CoreFoundation 0x367c4a97 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 26
21 CoreFoundation 0x367c683f __CFRunLoopDoSource1 + 166
22 CoreFoundation 0x367c760d __CFRunLoopRun + 520
23 CoreFoundation 0x36757ec3 CFRunLoopRunSpecific + 230
24 CoreFoundation 0x36757dcb CFRunLoopRunInMode + 58
25 GraphicsServices 0x35f1141f GSEventRunModal + 114
26 GraphicsServices 0x35f114cb GSEventRun + 62
27 UIKit 0x35601d69 -[UIApplication _run] + 404
28 UIKit 0x355ff807 UIApplicationMain + 670
29 Holler 0x00002d79 Holler + 7545
30 Holler 0x00002d44 Holler + 7492
Unfortunately the last 8 items in the stack trace don't appear to be symbolicated. Is there a way for me to do this? I'm assuming hte problem is related to ABRecordCopyValue however I'm not 100% certain. Since I don't know what the last two Holler calls are, I'm somewhat confused. Anybody have an idea about what I should do to narrow down the problem?
I believe the problem now resides within a specific method as the sequence of events (ABRecordCopyValue) followed by two Holler calls is repeated. Here's the code ... I'm using it to load up a user's phone book/contact list. Let me know if this provides any more details:
ContactLists *list = [ContactLists defaultLists];
//Delete the phone contacts, and load them
[list clearContacts];
//Load them
ABAddressBookRef addressbook = ABAddressBookCreate();
if( addressbook )
{
//Got this via http://stackoverflow.com/questions/4641229/code-example-for-abaddressbookcopyarrayofallpeopleinsourcewithsortordering
ABRecordRef source = ABAddressBookCopyDefaultSource(addressbook);
CFArrayRef sortedPeople = ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering(addressbook, source, kABPersonSortByFirstName);
//Sort them first
if( sortedPeople )
{
CFIndex contactCount = ABAddressBookGetPersonCount(addressbook);
for( int i = 0; i<contactCount; i++ )
{
ABRecordRef ref = CFArrayGetValueAtIndex(sortedPeople, i);
NSMutableString *fName = [[[NSMutableString alloc] init] autorelease];
NSMutableString *lName = [[[NSMutableString alloc] init] autorelease];
NSMutableDictionary *identifiers = [[[NSMutableDictionary alloc]init]autorelease];
if( ref )
{
//Get the user's name first
CFStringRef firstName = ABRecordCopyValue(ref, kABPersonFirstNameProperty);
if( firstName )
{
NSString *fn = [NSString stringWithFormat:#"%#",firstName];
if([fn hasPrefix:#"(null"])
[fName appendString:#""];
else
{
[fName appendString:[NSString stringWithFormat:#"%#", firstName]];
[fName setString:[fName stringByReplacingCharactersInRange:NSMakeRange(0,1) withString:[[fName substringToIndex:1]uppercaseString]]];
}
CFRelease(firstName);
}
CFStringRef lastName = ABRecordCopyValue(ref, kABPersonLastNameProperty);
if( lastName )
{
NSString *ln = [NSString stringWithFormat:#"%#",lastName];
if([ln hasPrefix:#"(null"])
[lName appendString:#""];
else
[lName appendString:[NSString stringWithFormat:#"%#",lastName]];
CFRelease(lastName);
}
//If there is no first name don't deal with adding this contact to the ContactsList
if( [fName isEqualToString:#""] )
{
continue;
}
//Handle phone and email contacts
ABMultiValueRef phoneRef = ABRecordCopyValue(ref, kABPersonPhoneProperty);
if(phoneRef)
{
for( int i = 0; i<ABMultiValueGetCount(phoneRef); i++ )
{
CFStringRef phone = ABMultiValueCopyValueAtIndex(phoneRef, i);
if (phone) {
//Create the contact and add them to the phone contactList
NSString *mobileLabel = (NSString *)ABMultiValueCopyLabelAtIndex(phoneRef, i);
if( [mobileLabel isEqualToString:(NSString *)kABPersonPhoneMobileLabel] )
[identifiers setValue:(NSString *)phone forKey:#"Mobile:"];
if( [mobileLabel isEqualToString:(NSString *)kABPersonPhoneIPhoneLabel] )
[identifiers setValue:(NSString *)phone forKey:#"iPhone:"];
if( [mobileLabel isEqualToString:(NSString *)kABPersonPhoneMainLabel] )
[identifiers setValue:(NSString *)phone forKey:#"Main:"];
if( [mobileLabel isEqualToString:(NSString *)kABWorkLabel] )
[identifiers setValue:(NSString *)phone forKey:#"Work:"];
if( [mobileLabel isEqualToString:(NSString *)kABHomeLabel] )
[identifiers setValue:(NSString *)phone forKey:#"Home:"];
if( [mobileLabel isEqualToString:(NSString *)kABOtherLabel] )
[identifiers setValue:(NSString *)phone forKey:#"Other:"];
CFRelease(phone);
[mobileLabel release];
}
}
CFRelease(phoneRef);
}
ABMultiValueRef emailRef = ABRecordCopyValue(ref, kABPersonEmailProperty);
if (emailRef) {
if (ABMultiValueGetCount(emailRef) > 0) {
CFStringRef email = ABMultiValueCopyValueAtIndex(emailRef, 0);
if (email) {
[identifiers setValue:(NSString *)email forKey:#"Email:"];
CFRelease(email);
}
}
CFRelease(emailRef);
}
if( [identifiers count] > 0 )
{
//This is where I believe the problem is happen as it's two calls to internal Holler models
[list addContact:[[[Contact alloc]initWithIdentifiers:identifiers firstName:fName lastName:lName]autorelease]];
}
}
}
CFRelease(sortedPeople);
}
CFRelease(addressbook);
CFRelease(source);
}
You need to have the stack trace symbolicated before anything educated can be said about where the crash is.
If you open the stack trace file in Xcode (Import button in the Organizer window) it will automatically be symbolicated with the matching binary and symbolic file....
that is if you have saved the binary/symbolic files - preferably by using the archive function.
If you have not saved symbolic files for that exact file then you can not symbolicate the crash log and would have to wildly guess the real cause.
You really need to symbolicate the Holler methods in the stack trace. Here's how:
Go to TestFlight --> Select the Builds tab, then click the Testers button under the build that you are having issues with. Scroll down to the bottom and click on the bit.ly link that can be used to manually notify testers. At the bottom of that page, it gives you the option to download the .ipa file that you previously uploaded. Download it.
Once downloaded to your computer, rename the file extension from .ipa to .zip. Then unarchive it, and you should get the .app file. Since you only have the stack trace and not the full crash report, you can't use XCode to symbolicate, but you can do symbolication manually using the instructions found here: http://www.bartlettpublishing.com/site/bartpub/blog/3/entry/311
Hope that helps, and I'd love to be a beta tester for your future apps!
Related
I am unable to find a whole lot of information about this and I'm having zero luck in any way that I try to narrow down where this problem is coming from so I'm hoping somebody here can give me a bit more information and potential leads on why I might be getting this error.
I'm plotting a data set in real time as the data set is constantly increasing through me constantly receiving new data. When I receive new data I take the time i receive it as the x and the value itself as y, this is how I generate my points.
Full Error: Terminating app due to uncaught exception 'CPTException', reason: 'Number of x and y values do not match'
I have looked at my data set before the crash, I have made sure my point creation was never failing neither had anything wrong with them. I'm guessing at this point that is has something to do with my version of Scatter Plot, probably in the numberOfRecordsForPlot function. It doesn't seem to crash anywhere in that function however. The crash doesn't happen until usually 10+ seconds in, but again its not consistent, and before it crashes and am getting perfectly working plotting.
Any light people can shed on this is very much appreciated.
PS: If people want to see code, let me know what, anything non standard I have verified to be functioning to the best of my ability, and anything to do with Scatter Plot is fairly standard.
-(NSUInteger)numberOfRecordsForPlot:(CPTPlot *)plot
{
//Translation: The array with key of the top of the first selected parameter
NSInteger curCount = [self.graphParams count];
NSLog(#"Current Count: %d", curCount);
if ([plot.identifier isEqual:#"Sel_1"] && (curCount >= 1) ) {
if ([self.graphParams objectAtIndex: 0] != nil) {
//NSString *myText = ((UITableViewCell *)[self.graphParams objectAtIndex: 0]).textLabel.text;
//NSInteger myNum = [[self.graphData objectForKey: myText] count];
//return [[self.graphData objectForKey: myText] count];
//return [[self.graphData objectForKey: ((UITableViewCell *)[self.graphParams objectAtIndex: 0]).textLabel.text] count];
return [[self.graphData objectForKey: [self.graphParams objectAtIndex: 0]] count];
}
else
return 0;
}
else if ([plot.identifier isEqual:#"Sel_2"] && (curCount >= 2) ) {
if ([self.graphParams objectAtIndex: 1] != nil)
//return [[self.graphData objectForKey: ((UITableViewCell *)[self.graphParams objectAtIndex: 1]).textLabel.text] count];
return [[self.graphData objectForKey: [self.graphParams objectAtIndex: 1]] count];
else
return 0;
}
else if ([plot.identifier isEqual:#"Sel_3"] && (curCount >= 3) ) {
if ([self.graphParams objectAtIndex: 2] != nil)
//return [[self.graphData objectForKey: ((UITableViewCell *)[self.graphParams objectAtIndex: 2]).textLabel.text] count];
return [[self.graphData objectForKey: [self.graphParams objectAtIndex: 2]] count];
else
return 0;
}
return 0;
}
-(NSNumber *)numberForPlot:(CPTPlot *)plot field:(NSUInteger)fieldEnum recordIndex:(NSUInteger)index
{
//Translation: The array with key of the top of the first selected parameter
NSValue *value = nil;
if ( [plot.identifier isEqual:#"Sel_1"] ) {
value = [[self.graphData objectForKey: [self.graphParams objectAtIndex:0]] objectAtIndex:index];
}
else if ( [plot.identifier isEqual:#"Sel_2"] ) {
value = [[self.graphData objectForKey: [self.graphParams objectAtIndex: 1]] objectAtIndex:index];
}
else if ( [plot.identifier isEqual:#"Sel_3"] ) {
value = [[self.graphData objectForKey: [self.graphParams objectAtIndex: 2]] objectAtIndex:index];
}
if (value != nil)
{
CGPoint point = [value CGPointValue];
if ( fieldEnum == CPTScatterPlotFieldX )
return [NSNumber numberWithFloat:point.x];
else if ( fieldEnum == CPTScatterPlotFieldY )
return [NSNumber numberWithFloat:point.y];
}
return [NSNumber numberWithFloat:0];
}
EDIT: Posted some scatter plot code where I think error may be coming from, but I dont know how useful this is to any of you. As always comment for additional requests and I'll be happy to provide anything that makes sense.
Make sure all access to the graphData dictionary and its contents are thread-safe. Core Plot does all of its datasource access and drawing on the main thread.
Always call -reloadData, -insertDataAtIndex:numberOfRecords:, and other Core Plot methods from the main thread.
I have also seen this. The exception happens when drawing the graph, not calling any of the data source functions.
Number of x and y values do not match
(
0 CoreFoundation 0x00007fff88f4df56 __exceptionPreprocess + 198
1 libobjc.A.dylib 0x00007fff851cfd5e objc_exception_throw + 43
2 CoreFoundation 0x00007fff88f4dd8a +[NSException raise:format:arguments:] + 106
3 CoreFoundation 0x00007fff88f4dd14 +[NSException raise:format:] + 116
4 CorePlot 0x0000000100027c31 -[CPTScatterPlot renderAsVectorInContext:] + 561
5 CorePlot 0x000000010004dd50 -[CPTLayer drawInContext:] + 96
6 CorePlot 0x000000010001d023 -[CPTPlot drawInContext:] + 99
7 QuartzCore 0x00007fff8a673701 CABackingStoreUpdate_ + 3221
8 QuartzCore 0x00007fff8a672616 _ZN2CA5Layer8display_Ev + 1086
9 QuartzCore 0x00007fff8a66a4e6 _ZN2CA5Layer17display_if_neededEPNS_11TransactionE + 560
10 QuartzCore 0x00007fff8a66949b _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 319
11 QuartzCore 0x00007fff8a669218 _ZN2CA11Transaction6commitEv + 274
12 QuartzCore 0x00007fff8a668819 _ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv + 63
13 CoreFoundation 0x00007fff88f0d8e7 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23
14 CoreFoundation 0x00007fff88f0d846 __CFRunLoopDoObservers + 374
15 CoreFoundation 0x00007fff88ee24a2 CFRunLoopRunSpecific + 258
16 HIToolbox 0x00007fff8d59c4d3 RunCurrentEventLoopInMode + 277
17 HIToolbox 0x00007fff8d5a3781 ReceiveNextEventCommon + 355
18 HIToolbox 0x00007fff8d5a360e BlockUntilNextEventMatchingListInMode + 62
19 AppKit 0x00007fff87df4e31 _DPSNextEvent + 659
20 AppKit 0x00007fff87df4735 -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] + 135
21 AppKit 0x00007fff87df1071 -[NSApplication run] + 470
22 AppKit 0x00007fff8806d244 NSApplicationMain + 867
23 0x0000000100001a62 main + 34
24 0x0000000100001a34 start + 52
)
My app is also MultiThreaded, but I have made sure that [thePlot setDataNeedsReloading] is called in the main thread, and I have ensured that all my data source callbacks are being called in the main thread.
I'm sure that somehow, CorePlot is making two calls to get my data, and I'm adding more data in between those 2 calls, and CorePlot is confused.
I am running the following code in the IOS 5.1 simulator:
Table* sparkFront =
[NSEntityDescription insertNewObjectForEntityForName:#"Table"
inManagedObjectContext:_context];
NSLog(#"%#", sparkFront);
NSEntityDescription* entity = [NSEntityDescription entityForName:#"Table"
inManagedObjectContext:_context];
NSDictionary* dict = [entity propertiesByName];
for (NSObject* key in [dict allKeys])
{
NSLog(#"%#", key);
}
sparkFront.columnValuesAddress = 0x606;
This code crashes with EXC_BAD_ACCESS on the last line. The Table object is a Core Data object implemented as follows:
#interface Table : NSManagedObject
#property (nonatomic) int32_t columnValuesAddress;
#end
I know Core Data doesn't natively do scalar types, but this is an IOS 5+ only app, and I was under the impression the un/boxing was done automatically. The output of the above code before the crash shows that my context and entity are good:
2012-07-20 22:17:52.714 otest[95147:7b03] <NSManagedObject: 0x9c87b20> (entity: Table; id: 0x9c86a80 <x-coredata:///Table/t2C0D90D5-E381-4BD0-B65D-8FC83C6D50DB2> ; data: {
columnValuesAddress = 0;
})
2012-07-20 22:17:52.716 otest[95147:7b03] columnValuesAddress
After the crash, the problem report shows the following:
Application Specific Information:
objc_msgSend() selector name: isNSNumber__
Simulator libSystem was initialized out of order.
Thread 0 Crashed:
0 libobjc.A.dylib 0x00635098 objc_msgSend + 12
1 CoreData 0x05c2e833 _PFManagedObject_coerceValueForKeyWithDescription + 483
2 CoreData 0x05bfe3d1 _sharedIMPL_setvfk_core + 209
3 CoreData 0x05c16687 _svfk_0 + 39
4 ECMCalTests 0x0187f8f1 -[ECMCalTests testInsertRecords] + 849 (ECMCalTests.m:73)
5 CoreFoundation 0x003f74ed __invoking___ + 29
6 CoreFoundation 0x003f7407 -[NSInvocation invoke] + 167
7 SenTestingKit 0x201039c4 -[SenTestCase invokeTest] + 184
8 SenTestingKit 0x20103868 -[SenTestCase performTest:] + 183
9 SenTestingKit 0x201034a9 -[SenTest run] + 82
10 SenTestingKit 0x20106db2 -[SenTestSuite performTest:] + 106
11 SenTestingKit 0x201034a9 -[SenTest run] + 82
12 SenTestingKit 0x20106db2 -[SenTestSuite performTest:] + 106
13 SenTestingKit 0x201034a9 -[SenTest run] + 82
14 SenTestingKit 0x20105e97 +[SenTestProbe runTests:] + 174
15 CoreFoundation 0x00492d51 +[NSObject performSelector:withObject:] + 65
16 otest 0x0000231c 0x1000 + 4892
17 otest 0x000025be 0x1000 + 5566
18 otest 0x00002203 0x1000 + 4611
19 otest 0x00001f8d 0x1000 + 3981
20 otest 0x00001f31 0x1000 + 3889
What am I doing wrong?
UPDATE: I implemented the setter/getter for the property according to the core data tutorial. It still crashes. It never hits a breakpoint in the setter so it is crashing before it even calls the setter. Am I hitting a bug in Apple's code?
#interface Table : NSManagedObject
{
int32_t columnValuesAddress;
}
#property (nonatomic) int32_t columnValuesAddress;
#end
#implementation Table
- (int32_t)columnValuesAddress
{
[self willAccessValueForKey:#"columnValuesAddress"];
int32_t address = columnValuesAddress;
[self didAccessValueForKey:#"columnValuesAddress"];
return address;
}
- (void)setColumnValuesAddress:(int32_t)address
{
[self willChangeValueForKey:#"columnValuesAddress"];
columnValuesAddress = address;
[self didChangeValueForKey:#"columnValuesAddress"];
}
- (void)setNilValueForKey:(NSString *)key
{
if ([key isEqualToString:#"columnValuesAddress"])
{
self.columnValuesAddress = 0;
}
else
{
[super setNilValueForKey:key];
}
}
#end
In the entity editor, you need to set your class. It is set for you when you create the core data class file with the file template. I created a class file without the template and thus the class wasn't set, so I was getting these errors. It will only auto box and un-box if it can see the class and see that you have it specified as assign.
I created a brand new project, created the model again from scratch, and copied over the test code from the old project. This new project works fine. I don't know why the old project doesn't work but at least there is a solution.
This is strange. Whenever I enable LLVM compiler optimization (-O/-O1 or higher) I get an EXC_BAD_ACCESS error when a property on my class is accessed. The property is accessed earlier in the code flow without a problem, but at "some point" (I know, it's vague) the app crashes.
I've looked at several other Stack Overflow questions re: strict aliasing but don't see (or understand) where I may be breaking that in my code. Here's the offending class: (crash indicated near the end of the class)
#import "MessageManager.h"
#import "NSURL+Additions.h"
#import "NSString+Guid.h"
static MessageManager *_instance = NULL;
#interface MessageManager ()
#property (nonatomic, strong) NSMutableDictionary *listeners;
#property (nonatomic, strong) NSMutableDictionary *senders;
#end
#implementation MessageManager
#synthesize listeners, senders;
+ (MessageManager *) getInstance
{
#synchronized(self)
{
if (self == [MessageManager class] && _instance == NULL) {
_instance = [[self alloc] init];
_instance.listeners = [NSMutableDictionary dictionary];
_instance.senders = [NSMutableDictionary dictionary];
}
}
return (_instance);
}
#pragma mark
#pragma mark Senders
- (void) addMessage:(Message *)message sender:(void (^) ())sender callback:(void (^) (Message *))callback
{
[self addMessage:message sender:sender callback:callback sendImmediately:NO];
}
- (void) addMessage:(Message *)message sender:(void (^) ())sender callback:(void (^) (Message *))callback sendImmediately:(BOOL)sendNow
{
message.id = [NSString stringWithGuid];
[senders setObject:[NSDictionary dictionaryWithObjectsAndKeys:message, #"message", [sender copy], #"sender", nil] forKey:message.id];
// note: callbacks use the message id and not the key, so that they remain tied to the message and not other keyed events
if (callback) [self registerListener:callback forKey:message.id];
if (sendNow) {
message.isSent = YES;
sender();
}
}
- (void) sendAll
{
[self sendAllForTags:nil];
}
- (void) sendAllForTags:(NSArray *)tags
{
typedef void (^SenderBlock) ();
[senders enumerateKeysAndObjectsUsingBlock:^(NSString *messageId, id wrapper, BOOL *stop) {
Message *message = (Message *)[(NSDictionary *)wrapper objectForKey:#"message"];
id sender = [(NSDictionary *)wrapper objectForKey:#"sender"];
BOOL validTag;
if (tags && tags.count) {
if (message.tags.count) {
validTag = false;
for (NSString *tag in tags) {
if ([message.tags containsObject:tag]) {
validTag = true; // found match! ok to send.
break;
}
}
} else validTag = false; // tags specified, but none in message, never send
} else validTag = true; // no tags specified, always send
if ((!message.isSent || message.isRepeatable) && validTag) {
message.isSent = YES;
((SenderBlock)sender)(); // send message!
}
}];
}
#pragma mark
#pragma mark Listeners
- (void) registerListener:(void (^) (Message *))listener forKey:(NSString *)key
{
if (![listeners objectForKey:key]) {
[listeners setObject:[NSMutableArray array] forKey:key];
}
[(NSMutableArray *)[listeners objectForKey:key] addObject:listener];
}
- (BOOL) handleOpenURL:(NSURL *)url
{
Message *message = [[Message alloc] initWithJson:[[url queryParams] objectForKey:#"message"]];
NSLog(#"%#", listeners); // <<<<----- CRASH HAPPENS HERE (or the first place in this method that "listeners" is referenced)
NSMutableArray *keyedListeners = (NSMutableArray *)[listeners objectForKey:message.key];
typedef void (^ListenerBlock)(Message *);
for (ListenerBlock keyedListener in keyedListeners) {
keyedListener(message);
}
return YES;
}
#end
NOTE: registerListener:forKey: is called several times BEFORE handleOpenUrl: gets called, without any error, even though it references the "listeners" property.
For context, this is part of a messaging framework I created that allows sending and receiving messages and events.
EDIT: Stack trace
0 MyApp 0x00026206 testflight_backtrace + 158
1 MyApp 0x00026e30 TFSignalHandler + 244
2 libsystem_c.dylib 0x36fc67ec _sigtramp + 48
3 MyApp 0x00024f7c -[MessageManager handleOpenURL:] (MessageManager.m:112)
4 MyApp 0x0001c29a -[WebViewController webView:shouldStartLoadWithRequest:navigationType:] (WebViewController.m:327)
5 UIKit 0x32492482 -[UIWebView webView:decidePolicyForNavigationAction:request:frame:decisionListener:] + 182
6 CoreFoundation 0x352cf7e3 __invoking___ + 67
7 CoreFoundation 0x3522a7b0 -[NSInvocation invoke] + 160
8 CoreFoundation 0x3522a3ce -[NSInvocation invokeWithTarget:] + 50
9 WebKit 0x338b1e0c -[_WebSafeForwarder forwardInvocation:] + 252
10 CoreFoundation 0x352cea82 ___forwarding___ + 666
11 CoreFoundation 0x3522964f _CF_forwarding_prep_0 + 47
12 CoreFoundation 0x352cf7e3 __invoking___ + 67
13 CoreFoundation 0x3522a7b0 -[NSInvocation invoke] + 160
14 WebCore 0x37060648 _ZL11SendMessageP12NSInvocation + 24
15 WebCore 0x37073b44 _ZL20HandleDelegateSourcePv + 80
16 CoreFoundation 0x352a0ad2 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 14
17 CoreFoundation 0x352a029e __CFRunLoopDoSources0 + 214
18 CoreFoundation 0x3529f044 __CFRunLoopRun + 652
19 CoreFoundation 0x352224a4 CFRunLoopRunSpecific + 300
20 CoreFoundation 0x3522236c CFRunLoopRunInMode + 104
21 GraphicsServices 0x3651e438 GSEventRunModal + 136
22 UIKit 0x32318e7c UIApplicationMain + 1080
23 MyApp 0x0001aa32 main (main.m:34)
24 MyApp 0x0001a9e7 start + 39
I think it is the blocks you are not correctly copying into the collection (listeners). Look at this question: Keep blocks inside a dictionary
There is a a very good write up on why you need to do this
In Objective-c, I am trying to get properties of some Object that contains about 14 property using the following code:
-(NSDictionary*) getPropertiesOfClass:(Class) clazz
{
NSMutableDictionary* dict = [NSMutableDictionary dictionary];
unsigned int outCount, i;
objc_property_t *properties = class_copyPropertyList(clazz, &outCount);
for(i = 0; i < outCount; i++)
{
objc_property_t _property = properties[i];
const char *propName = property_getName(_property);
if(propName)
{
const char *propType = getPropertyType(_property);
NSString *propertyName = [NSString stringWithCString:propName encoding:NSUTF8StringEncoding];
NSString *propertyType = [NSString stringWithCString:propType encoding:NSUTF8StringEncoding];
[dict setValue:propertyType forKey:propertyName];
}
}
free(properties);
return dict;
}
static const char *getPropertyType(objc_property_t property)
{
const char *attributes = property_getAttributes(property);
char buffer[1 + strlen(attributes)];
strcpy(buffer, attributes);
char *state = buffer, *attribute;
while ((attribute = strsep(&state, ",")) != NULL)
{
if (attribute[0] == 'T')
{
return (const char *)[[NSData dataWithBytes:(attribute + 3) length:strlen(attribute) - 4] bytes];
}
}
return "#";
}
But I got an exception (see below) However, When I try to use the same code to get the properties list of small objects (objects with 3 or 4 properties), the code works without any exceptions and get accurate results.
So, How to handle this error!!
Thanks.
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSConcreteData initWithBytes:length:copy:freeWhenDone:bytesAreVM:]: absurd length: 4294967294, maximum size: 2147483648 bytes'
*** Call stack at first throw:
(
0 CoreFoundation 0x0101e5a9 __exceptionPreprocess + 185
1 libobjc.A.dylib 0x01172313 objc_exception_throw + 44
2 CoreFoundation 0x00fd6ef8 +[NSException raise:format:arguments:] + 136
3 CoreFoundation 0x00fd6e6a +[NSException raise:format:] + 58
4 Foundation 0x00800b6b -[NSConcreteData initWithBytes:length:copy:freeWhenDone:bytesAreVM:] + 135
5 Foundation 0x00811801 -[NSData(NSData) initWithBytes:length:] + 72
6 solit 0x00033449 -[ObjectMapper(private) getPropertiesOfClass:] + 489
7 solit 0x00031fa5 -[ObjectMapper objectFromDictionary:object:] + 197
8 solit 0x000327b3 -[ObjectMapper objectFromDictionary:object:] + 2259
9 solit 0x00033913 -[NSDictionary(ObjectMapper) toObject:withTypes:] + 243
10 solit 0x00031474 -[JsonWSCaller call:types:error:] + 196
11 solit 0x0003f4c2 +[SummaryWSCaller getFastData:] + 354
12 solit 0x00006fd9 -[PartSearchResultView tableView:didSelectRowAtIndexPath:] + 233
13 UIKit 0x00110b68 -[UITableView _selectRowAtIndexPath:animated:scrollPosition:notifyDelegate:] + 1140
14 UIKit 0x00106b05 -[UITableView _userSelectRowAtPendingSelectionIndexPath:] + 219
15 Foundation 0x0082079e __NSFireDelayedPerform + 441
16 CoreFoundation 0x00fff8c3 __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 19
17 CoreFoundation 0x01000e74 __CFRunLoopDoTimer + 1220
18 CoreFoundation 0x00f5d2c9 __CFRunLoopRun + 1817
19 CoreFoundation 0x00f5c840 CFRunLoopRunSpecific + 208
20 CoreFoundation 0x00f5c761 CFRunLoopRunInMode + 97
21 GraphicsServices 0x012561c4 GSEventRunModal + 217
22 GraphicsServices 0x01256289 GSEventRun + 115
23 UIKit 0x000a7c93 UIApplicationMain + 1160
24 solit 0x00002289 main + 121
25 solit 0x00002205 start + 53
)
That's not related to the size of the class nor the number of properties.
This is probably because you have a problem in your memory mgmt. When there are not too much properties, the memory used to retrieve the property name and types in the const char* variables are still there, but when you start having too much properties to loop thru, these memory zones are erased by new values, hence the crash.
This is probably related to the fact that strsep is not reentrant too, so looping and using it multiple times uses the same internal char buffer each time.
You should make your getPropertyType method directly return the NSData object instead of the const char* bytes, and use NSString's initWithData:encoding: method to build the string from it (or move this initWithData:encoding: call to getPropertyType directly and make this return an NSString object directly. This way you will avoid managing pointers to memory zones that are to be autoreleased soon.
But your problem is probably that you forgot to check the validity of the attribute buffer and especially its length before trying to access the bytes in this buffer !
Especially you are using [NSData dataWithBytes:(attribute + 3) length:strlen(attribute) - 4] without checking that attribute is at least 4 characters long!
That's why the call to dataWithBytes:length: (that internally calls initWithBytes:length:copy:freeWhenDone:bytesAreVM:) crash with a NSInvalidArgumentException, telling that you pass it an absurd length of 4294967294 (which is -2 if interpreted as signed integer)
Hey fellas, while running through a debugger I am seeing the following appear the second time it sets the variables (timestamp and checksum are set through this method one after the other, it works fine when no DataFeedManager exists, but upon returning to it again it crashes when it's time to set the checksum):
Here is the function of interest:
//sets specified attribute to the passed in value while ensuring that only one instance of the DataFeedManager exists
-(void)setItemInDFMWhilePreservingEntityUniquenessForItem:(attribute)attr withValue:(id)value {
SJLog(#"CoreDataSingleton.m setItemInDFMWhilePreservingEntityUniquenessForItem");
NSError *error;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription
entityForName:#"DataFeedManager" inManagedObjectContext:[self managedObjectContext]];
[fetchRequest setEntity:entity];
NSUInteger numEntities = [[self managedObjectContext] countForFetchRequest:fetchRequest error:&error];
if (numEntities == NSNotFound) { // ERROR
//...
} else if (numEntities == 0) {
DataFeedManager *dfm = (DataFeedManager *)[NSEntityDescription insertNewObjectForEntityForName:#"DataFeedManager"
inManagedObjectContext:[self managedObjectContext]];
if (attr == checksumAttr) { //BLOCK OF INTEREST
NSString *tempVal = [[NSString alloc] initWithString:value];
[dfm setLastUpdateCheckSum:[NSString stringWithString:tempVal]];
} else if (attr == timeStampAttr) {
[dfm setTimeStamp:value];
}
} else { // more than zero entities
if (numEntities == 1) {
NSArray *fetchedObjects = [[self managedObjectContext] executeFetchRequest:fetchRequest error:&error];
if (attr == checksumAttr) { //BLOCK OF INTEREST
NSString *tempVal = [[NSString alloc] initWithString:value];
[[fetchedObjects objectAtIndex:0] setLastUpdateCheckSum:[NSString stringWithString:tempVal]]; //crashes at this line, after successfully going through the previous BLOCK OF INTEREST area
} else if (attr == timeStampAttr) {
[[fetchedObjects objectAtIndex:0] setTimeStamp:value];
}
} else { // ERROR: more than one entity
//...
}
} // else more than zero entities
[fetchRequest release];
}//setItemInDFMWhilePreservingEntityUniquenessForItem:withValue:
I have marked the areas of interest with //BLOCK OF INTEREST comments and have indicated upon which line the crash occurs (scroll right to see it!). Here is a readout of error from the console:
2011-04-22 17:18:10.924 Parking[26783:207] CoreDataSingleton.m setItemInDFMWhilePreservingEntityUniquenessForItem
2011-04-22 17:18:10.924 Parking[26783:207] -[__NSCFDictionary length]: unrecognized selector sent to instance 0xac34850
2011-04-22 17:18:10.970 Parking[26783:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFDictionary length]: unrecognized selector sent to instance 0xac34850'
*** Call stack at first throw:
(
0 CoreFoundation 0x011a0be9 __exceptionPreprocess + 185
1 libobjc.A.dylib 0x012f55c2 objc_exception_throw + 47
2 CoreFoundation 0x011a26fb -[NSObject(NSObject) doesNotRecognizeSelector:] + 187
3 CoreFoundation 0x01112366 ___forwarding___ + 966
4 CoreFoundation 0x01111f22 _CF_forwarding_prep_0 + 50
5 Foundation 0x00c4d1e1 -[NSPlaceholderString initWithString:] + 162
6 Foundation 0x00c562c2 +[NSString stringWithString:] + 72
7 Parking 0x0000e4d4 -[CoreDataSingleton setItemInDFMWhilePreservingEntityUniquenessForItem:withValue:] + 774
8 Parking 0x00008bb4 -[DataUpdater allDataRetrievedWithSuccess:withError:] + 225
9 Parking 0x0000952e -[DataUpdater dataDownloadCompleted:forFunc:withData:withError:] + 769
10 Parking 0x00010bb5 -[DataRetriever finish] + 432
11 Parking 0x00010e75 -[DataRetriever connectionDidFinishLoading:] + 36
12 Foundation 0x00c61172 -[NSURLConnection(NSURLConnectionReallyInternal) sendDidFinishLoading] + 108
13 Foundation 0x00c610cb _NSURLConnectionDidFinishLoading + 133
14 CFNetwork 0x0348e606 _ZN19URLConnectionClient23_clientDidFinishLoadingEPNS_26ClientConnectionEventQueueE + 220
15 CFNetwork 0x03559821 _ZN19URLConnectionClient26ClientConnectionEventQueue33processAllEventsAndConsumePayloadEP20XConnectionEventInfoI12XClientEvent18XClientEventParamsEl + 293
16 CFNetwork 0x03559b0f _ZN19URLConnectionClient26ClientConnectionEventQueue33processAllEventsAndConsumePayloadEP20XConnectionEventInfoI12XClientEvent18XClientEventParamsEl + 1043
17 CFNetwork 0x03484e3c _ZN19URLConnectionClient13processEventsEv + 100
18 CFNetwork 0x03484cb7 _ZN17MultiplexerSource7performEv + 251
19 CoreFoundation 0x0118201f __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 15
20 CoreFoundation 0x010e019d __CFRunLoopDoSources0 + 333
21 CoreFoundation 0x010df786 __CFRunLoopRun + 470
22 CoreFoundation 0x010df240 CFRunLoopRunSpecific + 208
23 CoreFoundation 0x010df161 CFRunLoopRunInMode + 97
24 GraphicsServices 0x01414268 GSEventRunModal + 217
25 GraphicsServices 0x0141432d GSEventRun + 115
26 UIKit 0x0004e42e UIApplicationMain + 1160
27 Parking 0x00002698 main + 102
28 Parking 0x00002629 start + 53
)
terminate called after throwing an instance of 'NSException'
I believe it has something to do with copying the string adequately (can't set a string I don't own to the store). I have tried placing [value copy] as well as &value(saw this sort of thing work for someone else, so I thought I would give it a shot) to no avail. Shouldn't my current method adequately take ownership of the string? I still can't figure out what I am doing wrong. Any help appreciated. Thanks!
Best guess (based in part on this answer) is that you're passing in a released object as the value when you call the method the second time, or possibly that value is of class NSDictionary on your second time through – it's not clear from this code snippet why your method takes an argument of type id and then blithely treats it as an instance of NSString, but this may be part of the problem.
Note that your -setItemInDFMWhilePreservingEntityUniquenessForItem:withValue: accepts an arbitrary object in its second argument (type id).
Inside the method, you do:
NSString *tempVal = [[NSString alloc] initWithString:value];
Unless value is an Objective-C string, this will crash your program. In fact, your crash log shows that in that particular execution value was an NSDictionary. You need to make sure that value is an NSString.
Also, note that you own the string you’re assigning to tempVal since you’ve used +alloc. Don’t forget to release that string.