We are facing iOS crash issue in our one SDK library written in objective-c. This objective-c library is being invoked from swift app developed by our customer.
Following is the code snippet from our sdk, where we are creating multiple threads:-
//Create a queue to collect attributes in parallel
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
//Create group to wait on the task scheduled in global queue
dispatch_group_t group = dispatch_group_create();
// Collect all information1
dispatch_group_async(group, queue, ^{
info1 = [self getInformation1];
});
// Collect all information2
dispatch_group_async(group, queue, ^{
info2 = [self getInformation2];
});
// Collect all information3
dispatch_group_async(group, queue, ^{
info3 = [self getInformation3];
});
// Collect all information4
dispatch_group_async(group, queue, ^{
info4 = [self getInformation4];
});
// Collect all information5
dispatch_group_async(group, queue, ^{
info5 = [self getInformation5];
});
// wait on the group to block the current thread.
int64_t time_delay = 3.0;
dispatch_time_t timeout = dispatch_time(DISPATCH_TIME_NOW, time_delay * NSEC_PER_SEC);
long success = dispatch_group_wait(group,timeout);
if(success != 0) {
//Log data to check which bucket is not complete
[Logger writeLogWithSeverity:kLogERROR message:info1];
[Logger writeLogWithSeverity:kLogERROR message:info2];
[Logger writeLogWithSeverity:kLogERROR message:info3];
[Logger writeLogWithSeverity:kLogERROR message:info4];
[Logger writeLogWithSeverity:kLogERROR message:info5];
}
Is this is ideal way or is there any better way to create concurrent threads?
Following are couple of stack traces of the crashes
1)
Exception Type: EXC_BAD_ACCESS (SIGBUS)
Exception Codes: 0x00000000 at 0x0000000323f7bec8
Crashed Thread: 0
Thread 0 Crashed:
0 libobjc.A.dylib 0x000000018193c1a0 0x181918000 + 147872 (objc_retain + 16)
1 abcMobile 0x0000000104365cbc 0x1041c8000 + 1694908 -[DeviceInventory notifyCollectingdeviceInfo:] (DeviceInventory.m:215 + 28)
2 abcMobile 0x0000000104365b78 0x1041c8000 + 1694584 -[DeviceInventory startCollectingdeviceInfo] (DeviceInventory.m:206 + 0)
3 libdispatch.dylib 0x0000000182058b24 0x182057000 + 6948 ( + 24)
4 libdispatch.dylib 0x0000000182058ae4 0x182057000 + 6884 ( + 16)
5 libdispatch.dylib 0x00000001820656e0 0x182057000 + 59104 ( + 1012)
6 CoreFoundation 0x000000018270f070 0x182621000 + 974960 ( + 12)
7 CoreFoundation 0x000000018270cbc8 0x182621000 + 965576 ( + 2272)
8 CoreFoundation 0x000000018262cda8 0x182621000 + 48552 (CFRunLoopRunSpecific + 552)
9 GraphicsServices 0x000000018460f020 0x184604000 + 45088 (GSEventRunModal + 100)
10 UIKit 0x000000018c60d78c 0x18c2f0000 + 3266444 (UIApplicationMain + 236)
11 abcMobile 0x00000001041ccc40 0x1041c8000 + 19520 main (main.swift:14 + 20)
12 libdyld.dylib 0x00000001820bdfc0 0x1820bd000 + 4032 ( + 4)
Crashing code :- [self.delegate didCompletedCollectingInformation:deviceInfo];
didCompletedCollectingInformation is a call-back function
2)
Exception Type: EXC_BAD_ACCESS (SIGBUS)
Exception Codes: 0x00000000 at 0x00000007943dbec8
Crashed Thread: 18
Thread 18 Crashed:
0 libobjc.A.dylib 0x0000000182f3c1a0 0x182f18000 + 147872 (objc_retain + 16)
1 abcMobile 0x0000000100c0150c 0x100a64000 + 1692940 -[DeviceInventory didFailWithError:] (DeviceInventory.m:144 + 28)
2 CoreFoundation 0x0000000183cf8c3c 0x183c21000 + 883772 ( + 20)
3 CoreFoundation 0x0000000183cf81b8 0x183c21000 + 881080 ( + 428)
4 CoreFoundation 0x0000000183cf7f14 0x183c21000 + 880404 ( + 216)
5 CoreFoundation 0x0000000183d7584c 0x183c21000 + 1394764 ( + 1408)
6 CoreFoundation 0x0000000183c2ef38 0x183c21000 + 57144 (_CFXNotificationPost + 384)
7 Foundation 0x000000018469fbbc 0x184699000 + 27580 ( + 68)
8 abcMobile 0x0000000100bf7f80 0x100a64000 + 1654656 +[Errors sendErrorNotifactionForErrorCode:] (Errors.m:405 + 64)
9 abcMobile 0x0000000100bf101c 0x100a64000 + 1626140 +[NetworkInfo information1] (NetworkInfo.m:711 + 0)
10 abcMobile 0x0000000100bfb9fc 0x100a64000 + 1669628 -[Services information1] (Services.m:391 + 20)
11 abcMobile 0x0000000100c058b4 0x100a64000 + 1710260 -[DeviceInventory getInformation1] (DeviceInventory.m:635 + 56)
12 abcMobile 0x0000000100c0268c 0x100a64000 + 1697420 __39-[DeviceInventory getdeviceInfo]_block_invoke.163 (DeviceInventory.m:256 + 16)
13 libdispatch.dylib 0x0000000183658aa0 0x183657000 + 6816 ( + 24)
14 libdispatch.dylib 0x0000000183658a60 0x183657000 + 6752 ( + 16)
15 libdispatch.dylib 0x000000018369a5f0 0x183657000 + 275952 ( + 1148)
16 libdispatch.dylib 0x000000018369a110 0x183657000 + 274704 ( + 112)
17 libsystem_pthread.dylib 0x000000018398bfac 0x18398b000 + 4012 (_pthread_wqthread + 1176)
Crashing code :- if([self.delegate respondsToSelector:#selector(didFailWithError:)])
Here, didFailWithError is a call-back function
We are unable to find the root cause of this crash as it is very random issue. Does anyone have any idea how to fix this crash issue?
Any pointers will be very helpful as we are struck on this issue.
Related
I have two operations fetching a value. I only care about the sum both values. And I don't care about the value at all if it takes too long.
So I thought it would be an easy task for GCD using groups. Unfortunately, the below code only works fine on iOS 9. Each time I have no matching calls of dispatch_group_enter()/dispatch_group_leave() I get a crash.
The documentation states clearly that I have to match both call. But when I use a timeout on dispatch_group_wait(), it is impossible to have the same amount of leave calls as enter calls; that is the whole point of specifying a timeout.
So is this a known bug in iOS 8? Am I doing something wrong? Is there another solution to my initial problem that works on iOS 8 as well?
EDIT: Actually we can boil it down to this:
var sync_group: dispatch_group_t = dispatch_group_create();
dispatch_group_enter(sync_group);
let maxWait = dispatch_time(DISPATCH_TIME_NOW, Int64(60 * NSEC_PER_SEC))
let result = dispatch_group_wait(sync_group, maxWait)
sync_group = dispatch_group_create();
Works as expected on iOS 9 but does crash on iOS 8 on the last line because the old dispatch_group_t instance can not be release. Any easy workarounds?
EDIT 2: Turns out it is broken on iOS 9.0 too. It only works as as it should in iOS 9.1+.
Original Code:
let qualityOfServiceClass = QOS_CLASS_BACKGROUND
let backgroundQueue = dispatch_get_global_queue(qualityOfServiceClass, 0)
dispatch_async(backgroundQueue, {
/* We want this method to block until the network code succeeded. */
let sync_group: dispatch_group_t = dispatch_group_create();
/* Start async operation 1. */
dispatch_group_enter(sync_group);
self.someAsyncOperation1({(value: Int, finalValue: Bool) in
if (finalValue) {
valOp1 = value
dispatch_group_leave(sync_group);
}
})
/* Start async operation 2. */
dispatch_group_enter(sync_group);
self.someAsyncOperation2({(value: Int, finalValue: Bool) in
if (finalValue) {
valOp2 = value
dispatch_group_leave(sync_group)
}
})
/* Block current thread until all leaves were called. If it takes more then 60 sec we don't care and let go. */
let maxWait = dispatch_time(DISPATCH_TIME_NOW, Int64(60 * NSEC_PER_SEC))
let result = dispatch_group_wait(sync_group, maxWait)
if (result > 0) {
/* This will result in a crash when we leave the scope: SIGTRAP in dispatch_semaphore_dispose */
return
}
dispatch_async(dispatch_get_main_queue(), {
let newValue = valOp1 + valOp2
self.lastKnownNotificationCombinedCounter = newValue
success(newValue)
})
})
The actual crash loops like that:
Exception Type: SIGTRAP
Exception Codes: #0 at 0x3958a2a4
Thread 2 Crashed:
0 libdispatch.dylib 0x3958a2a4 _dispatch_semaphore_dispose$VARIANT$mp + 48
1 libdispatch.dylib 0x3958b491 _dispatch_dispose$VARIANT$mp + 30
2 libdispatch.dylib 0x3957ea8f -[OS_dispatch_object _xref_dispose] + 44
3 myApp 0x00176a24 block_destroy_helper67 + 354
4 myApp 0x00176ab8 0x2e000 + 1346232
5 myApp 0x00178334 0x2e000 + 1352500
6 libsystem_blocks.dylib 0x395d3adb _Block_release + 216
7 Foundation 0x2c4143b9 -[NSBlockOperation dealloc] + 58
8 libobjc.A.dylib 0x39036d57 objc_object::sidetable_release(bool) + 164
9 libobjc.A.dylib 0x390371a9 (anonymous namespace)::AutoreleasePoolPage::pop(void*) + 402
10 libdispatch.dylib 0x39589423 _dispatch_root_queue_drain + 1176
11 libdispatch.dylib 0x3958a1fb _dispatch_worker_thread3 + 104
12 libsystem_pthread.dylib 0x396fae25 _pthread_wqthread + 666
13 libsystem_pthread.dylib 0x396fab78 start_wqthread + 6
I came up with this workaround:
private let MAX_TRIES = 20;
func dispatch_group_wait_ios8Safe(group: dispatch_group_t, _ timeout: dispatch_time_t) -> Int {
if #available(iOS 9, *) {
/* Just forward the call. */
return dispatch_group_wait(group, timeout)
} else {
/* Forward the call to original function and store result. */
let firstResult = dispatch_group_wait(group, timeout)
var result = firstResult, tries = 0
while(result > 0 && tries < MAX_TRIES) {
dispatch_group_leave(group)
result = dispatch_group_wait(group, DISPATCH_TIME_NOW)
tries += 1
}
/* Return original result. */
return firstResult
}
}
So until someone comes up with a better solution I stick with this.
Using the Google Analytics library for iOS version 3.0.9, (and 3.0.x in general), we see a lot of crashes like the one below.
They appeared to occur randomly.
Exception Type: SIGBUS
Exception Codes: BUS_ADRALN at 0xe756c0
Crashed Thread: 19
Thread 19 Crashed:
0 libsystem_platform.dylib 0x39e02e18 0x39e01000 + 7704
1 CoreFoundation 0x2bfd0d6f 0x2bf92000 + 257391
2 CoreFoundation 0x2c0716a3 0x2bf92000 + 915107
3 CoreFoundation 0x2c070417 0x2bf92000 + 910359
4 CoreFoundation 0x2bfd4a0b 0x2bf92000 + 272907
5 Communicator 0x00714541 +[GAIUsageTracker trackTarget:action:] + 193
6 Communicator 0x007049b3 -[GAITrackerImpl send:] + 47
7 Communicator 0x00157b8d __66+[xxx]_block_invoke (xxx.m:305)
8 libdispatch.dylib 0x39ca58cb 0x39ca4000 + 6347
9 libdispatch.dylib 0x39caeda3 0x39ca4000 + 44451
10 libdispatch.dylib 0x39cafcd7 0x39ca4000 + 48343
11 libsystem_pthread.dylib 0x39e06e31 0x39e06000 + 3633
It turns out that the GAI library is not as thread-safe as it claims. We were able to fix our Google Analytics crashes by serializing the calls.
(void (^)(void))block = {
// your analytics call, eg
[[[GAI sharedInstance] defaultTracker] send:....];
};
static dispatch_queue_t theQueue;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
theQueue = dispatch_queue_create("Analytics Queue", DISPATCH_QUEUE_SERIAL);
});
dispatch_async(theQueue, block);
So all calls to the tracker are executed in code blocks serialized on the same queue ("theQueue" above), which forces only one code block to execute at a time.
I have recorded a crash of my app, but the last line in my app (5 Control) points just to the method begin. How do I know in which line the problem is?
0 CoreFoundation 0x185f0af50 __exceptionPreprocess + 132
1 libobjc.A.dylib 0x1924141fc objc_exception_throw + 60
2 CoreFoundation 0x185f0fc04 -[NSObject(NSObject) doesNotRecognizeSelector:] + 220
3 CoreFoundation 0x185f0d930 ___forwarding___ + 912
4 CoreFoundation 0x185e2d5dc _CF_forwarding_prep_0 + 92
5 Control 0x10005acb4 -[PaymillPaymentService handleTransactionListRequest:] (PaymillPaymentService.m:211)
6 Foundation 0x186a7416c __103+[__NSOperationInternal _observeValueForKeyPath:ofObject:changeKind:oldValue:newValue:indexes:context:]_block_invoke96 + 28
7 libdispatch.dylib 0x1929ec014 _dispatch_call_block_and_release + 24
8 libdispatch.dylib 0x1929ebfd4 _dispatch_client_callout + 16
9 libdispatch.dylib 0x1929f32b8 _dispatch_root_queue_drain + 556
10 libdispatch.dylib 0x1929f34fc _dispatch_worker_thread2 + 76
11 libsystem_pthread.dylib 0x192b816bc _pthread_wqthread + 356
12 libsystem_pthread.dylib 0x192b8154c start_wqthread + 4
Here the [lengthy] method code. I see a couple of places where I can add the check but how to I know it for sure that I fixed the issue? The problem is sporadical and I cannot reproduce it easily.
- (void)handleTransactionListRequest:(ServiceRequest *)serviceRequest
{
LRURLRequestOperation* operation = serviceRequest.operation;
NSHTTPURLResponse *response = (NSHTTPURLResponse *)operation.URLResponse;
if (response.statusCode == 200)
{
if (operation.responseData)
{
NSError *parserError = nil;
NSDictionary *data = [NSJSONSerialization JSONObjectWithData:operation.responseData options:0 error:&parserError];
//NSLog(#"%#", data);
if (!parserError)
{
NSArray* transactions = [data objectForKey:#"data"];
if (0 == serviceRequest.currentOffset)
{
NSNumber* totalCountObj = [data objectForKey:#"data_count"];
serviceRequest.totalCount = [totalCountObj intValue];
}
int loadedCount = 0;
if (transactions)
{
for (id object in transactions)
{
TransactionInfo* info = [self createTransactionFrom:object];
[serviceRequest.transactionList addTransaction:info];
[info release];
loadedCount++;
}
}
if (loadedCount + serviceRequest.currentOffset >= serviceRequest.totalCount)
{
if ([serviceRequest.delegate respondsToSelector:#selector(transactionListLoadingComplete:)])
[serviceRequest.delegate transactionListLoadingComplete:serviceRequest];
serviceRequest.transactionList.timeStamp = [[NSDate date] timeIntervalSince1970];
NSLog(#"COMPLETE: %d transaction loaded ", serviceRequest.totalCount);
}
else
{
serviceRequest.currentOffset += loadedCount;
bool needToContinue = YES;
if ([serviceRequest.delegate respondsToSelector:#selector(transactionListLoadingContinue:)])
needToContinue = [serviceRequest.delegate transactionListLoadingContinue];
if (needToContinue)
{
[self continueRetrievingTransactionListFor:serviceRequest];
NSLog(#"CONTINUE: %d of %d loaded ", serviceRequest.currentOffset, serviceRequest.totalCount);
}
}
return; // all OK cases
}
}
}
if ([serviceRequest.delegate respondsToSelector:#selector(transactionListLoadingFailed:with:)])
[serviceRequest.delegate transactionListLoadingFailed:serviceRequest with:response.statusCode];
NSLog(#"ERROR: Loading Transactions Response Code: %ld", (long)response.statusCode);
}
Short Answer:
You are sending a message to an object that cannot validly respond to it. The stack trace is telling you that when you make the call [PaymillPaymentService handleTransactionListRequest:] that PaymillPaymentService cannot accept handleTransactionListRequest.
Long answer:
Look at the stack trace here:
5 Control 0x10005acb4 -[PaymillPaymentService handleTransactionListRequest:] (PaymillPaymentService.m:211)
This is telling you that in the file PaymillPaymentService.m on line 211 you are sending PaymillPaymentService the message handleTransactionListRequest to which it cannot validly respond. In your discussion with rmaddy, Hot Licks, and Paulc11 you mentioned that line 211 is the function entry for handleTransactionListRequest (in whatever file it resides). If that's the case it is coincidental.
If you want further follow up you need to post PaymillPaymentService.m and ensure that you include all the line numbers.
for some reason i have a dispatch_async thread, and it crashes unless i have a NSLog() method executed in front of it. the block runs a method that retrieves a username from a database.
crash:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
user_web_communicator *usrWeb = [[user_web_communicator alloc]init];
NSString *author = [usrWeb getUsernameFromID:author_string];
[_author_label setText:[NSString stringWithFormat:#"Author: %#",author]];
});
working:
NSLog(#"Fetching author for id: %#",author_string);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
user_web_communicator *usrWeb = [[user_web_communicator alloc]init];
NSString *author = [usrWeb getUsernameFromID:author_string];
[_author_label setText:[NSString stringWithFormat:#"Author: %#",author]];
});
error
2013-08-19 13:56:06.149 Poll Me[4995:c07] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '{
Rows: AsyncImageView:0x827aa00.minX == 10 + 1*0x827b8d0.marker +
-1*0x8281210.marker + 0.5*0x8281260.marker AsyncImageView:0x827aa00.minY == 27.5 + -1*0x827b910.marker +
-1*0x82812a0.marker + 0.5*0x82812e0.marker + 0.5*0x82823f0.marker + -0.5*AsyncImageView:0x827aa00.Height Regular_Cell:0x827a400.Height == 56 + 1*0x82823f0.marker Regular_Cell:0x827a400.Width == 320 +
1*0x8281ee0.marker Regular_Cell:0x827a400.minX == 0 +
1*0x8281740.marker + -0.5*0x8281ee0.marker
Regular_Cell:0x827a400.minY == 46 + 1*0x8281b30.marker +
-0.5*0x82823f0.marker UILabel:0x827a8e0.Width == 0 + 1*0x827b730.marker + 1*0x827b790.marker + -1*0x827b7d0.marker +
1*UILabel:0x827adc0.Width UILabel:0x827a8e0.minX == 18 +
1*0x827b7d0.marker + 1*0x827b8d0.marker + -1*0x8281210.marker +
0.5*0x8281260.marker + 1*AsyncImageView:0x827aa00.Width UILabel:0x827a8e0.minY == 19.5 + -1*0x827b810.marker +
1*0x827b890.marker + -1*0x827b910.marker + -1*0x82812a0.marker +
0.5*0x82812e0.marker + 0.5*0x82823f0.marker + 0.5*AsyncImageView:0x827aa00.Height + -1*UILabel:0x827a8e0.Height + -1*UILabel:0x827b140.Height UILabel:0x827adc0.minX == 18 + 1*0x827b730.marker + 1*0x827b8d0.marker + -1*0x8281210.marker +
0.5*0x8281260.marker + 1*AsyncImageView:0x827aa00.Width UILabel:0x827adc0.minY == 20.5 + 1*0x827b6f0.marker +
-1*0x82812a0.marker + 0.5*0x82812e0.marker UILabel:0x827b140.minX == 18 + 1*0x827b850.marker + 1*0x827b8d0.marker + -1*0x8281210.marker +
0.5*0x8281260.marker + 1*AsyncImageView:0x827aa00.Width UILabel:0x827b140.minY == 27.5 + 1*0x827b890.marker +
-1*0x827b910.marker + -1*0x82812a0.marker + 0.5*0x82812e0.marker + 0.5*0x82823f0.marker + 0.5*AsyncImageView:0x827aa00.Height + -1*UILabel:0x827b140.Height UITableViewCellContentView:0x827a560.Height == 55 +
1*0x82812e0.marker UITableViewCellContentView:0x827a560.Width == 300
+ 1*0x8281260.marker UITableViewCellContentView:0x827a560.minX == 0 + 1*0x8281210.marker + -0.5*0x8281260.marker
UITableViewCellContentView:0x827a560.minY == 0.5 + 1*0x82812a0.marker
+ -0.5*0x82812e0.marker objective == <> + <750:-1>*0x8280fc0.negError + <250:-1>*0x8280fc0.posErrorMarker + <750:-1>*0x8281030.negError + <250:-1>*0x8281030.posErrorMarker
Constraints: Marker:0x8281210.marker
Marker:0x8281260.marker
Marker:0x82812a0.marker (Integralization adjustment:0.5) Marker:0x82812e0.marker
Marker:0x8281740.marker
Marker:0x8281b30.marker
Marker:0x8280fc0.posErrorMarker
Marker:0x8281030.posErrorMarker
Marker:0x827b6f0.marker
Marker:0x827b730.marker
Marker:0x827b790.marker
Marker:0x827b7d0.marker
Marker:0x827b810.marker
Marker:0x827b850.marker
Marker:0x827b890.marker
Marker:0x827b8d0.marker
Marker:0x827b910.marker
Marker:0x8281ee0.marker
Marker:0x82823f0.marker }: internal
error. Cannot find an outgoing row head for incoming head
0x8280fc0.negError, which should never happen.'
* First throw call stack: (0x195d012 0x166ae7e 0x195cdeb 0xefef89 0xf01fcf 0xf025c7 0xf0d58f 0xf0d6d4 0x7d860a 0x7e02af 0x7e03be
0x2e7601 0x49484e 0x354ced 0x2e940c 0x354a7b 0x359919 0x3599cf
0x3421bb 0x352b4b 0x2ef2dd 0x167e6b0 0x17dfc0 0x17233c 0x172150
0xf00bc 0xf1227 0xf18e2 0x1925afe 0x1925a3d 0x19037c2 0x1902f44
0x1902e1b 0x29be7e3 0x29be668 0x29effc 0x1e5ed 0x1d75) 2013-08-19
13:56:06.149 Poll Me[4995:4f03] * Terminating app due to uncaught
exception 'NSInternalInconsistencyException', reason: '{ Rows:
AsyncImageView:0x827aa00.minX == 10 + 1*0x827b8d0.marker +
-1*0x8281210.marker + 0.5*0x8281260.marker AsyncImageView:0x827aa00.minY == 27.5 + -1*0x827b910.marker +
-1*0x82812a0.marker + 0.5*0x82812e0.marker + 0.5*0x82823f0.marker + -0.5*AsyncImageView:0x827aa00.Height Regular_Cell:0x827a400.Height == 56 + 1*0x82823f0.marker Regular_Cell:0x827a400.Width == 320 +
1*0x8281ee0.marker Regular_Cell:0x827a400.minX == 0 +
1*0x8281740.marker + -0.5*0x8281ee0.marker
Regular_Cell:0x827a400.minY == 46 + 1*0x8281b30.marker +
-0.5*0x82823f0.marker UILabel:0x827a8e0.Width == 0 + 1*0x827b730.marker + 1*0x827b790.marker + -1*0x827b7d0.marker +
1*UILabel:0x827adc0.Width UILabel:0x827a8e0.minX == 18 +
1*0x827b7d0.marker + 1*0x827b8d0.marker + -1*0x8281210.marker +
0.5*0x8281260.marker + 1*AsyncImageView:0x827aa00.Width UILabel:0x827a8e0.minY == 19.5 + -1*0x827b810.marker +
1*0x827b890.marker + -1*0x827b910.marker + -1*0x82812a0.marker +
0.5*0x82812e0.marker + 0.5*0x82823f0.marker + 0.5*AsyncImageView:0x827aa00.Height + -1*UILabel:0x827a8e0.Height + -1*UILabel:0x827b140.Height UILabel:0x827adc0.minX == 18 + 1*0x827b730.marker + 1*0x827b8d0.marker + -1*0x8281210.marker +
0.5*0x8281260.marker + 1*AsyncImageView:0x827aa00.Width UILabel:0x827adc0.minY == 20.5 + 1*0x827b6f0.marker +
-1*0x82812a0.marker + 0.5*0x82812e0.marker UILabel:0x827b140.minX == 18 + 1*0x827b850.marker + 1*0x827b8d0.marker + -1*0x8281210.marker +
0.5*0x8281260.marker + 1*AsyncImageView:0x827aa00.Width UILabel:0x827b140.minY == 27.5 + 1*0x827b890.marker +
-1*0x827b910.marker + -1*0x82812a0.marker + 0.5*0x82812e0.marker + 0.5*0x82823f0.marker + 0.5*AsyncImageView:0x827aa00.Height + -1*UILabel:0x827b140.Height UITableViewCellContentView:0x827a560.Height == 55 +
1*0x82812e0.marker UITableViewCellContentView:0x827a560.Width == 300
+ 1*0x8281260.marker UITableViewCellContentView:0xlibc++abi.dylib: terminate called throwing an exception827a560.minX == 0 +
1*0x8281210.marker + -0.5*0x8281260.marker
UITableViewCellContentView:0x827a560.minY == 0.5 + 1*0x82812a0.marker
+ -0.5*0x82812e0.marker objective == <> + <750:-1>*0x8280fc0.negError + <250:-1>*0x8280fc0.posErrorMarker + <750:-1>*0x8281030.negError + <250:-1>*0x8281030.posErrorMarker
Constraints: Marker:0x8281210.marker
Marker:0x8281260.marker
Marker:0x82812a0.marker (Integralization adjustment:0.5) Marker:0x82812e0.marker
Marker:0x8281740.marker Marker:0x8281b30.marker
Marker:0x8280fc0.posErrorMarker
Marker:0x8281030.posErrorMarker
Marker:0x827b6f0.marker
Marker:0x827b730.marker
Marker:0x827b790.marker
Marker:0x827b7d0.marker
Marker:0x827b810.marker
Marker:0x827b850.marker
Marker:0x827b890.marker
Marker:0x827b8d0.marker
Marker:0x827b910.marker
Marker:0x8281ee0.marker
Marker:0x82823f0.marker }: internal
error. Cannot find an outgoing row head for incoming head
0x8280fc0.negError, which should never happen.'
* First throw call stack: (0x195d012 0x166ae7e 0x195cdeb 0xefef89 0xf01fcf 0xf020d3 0x7d86dc 0x7d9280 0x7dd4a3 0x3f7e3c 0x3f8022
0x3f8064 0x2f33b 0x277553f 0x2787014 0x27782e8 0x2778450 0x92710e72
0x926f8d2a) (lldb)
can you please tell me why this could be happening? i dont want to keep the NSLog() there because it runs it several times and gets in the way when trying to read output. Thank you in advance =)
It is undefined behavior to set the text property of a label in a background thread, or any other UI changes for that matter. Since it is undefined behavior I can not explain why it works with the NSLog but you need to dispatch setting the label's text to the main thread.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
user_web_communicator *usrWeb = [[user_web_communicator alloc]init];
NSString *author = [usrWeb getUsernameFromID:author_string];
dispatch_sync(dispatch_get_main_queue(), ^{
[_author_label setText:[NSString stringWithFormat:#"Author: %#",author]];
})
});
The crash log is below.
Do you know any particular reason why might [UIScrollView removeFromSuperview] can crash? The scrollview contains view hierarchy with different types of UIViews. I also finds that the ad hoc version crash often not the debug version. I could not find any reason for that.
Same viewcontroller is loaded in a different flow in iPhone that works fine. But in iPad it crashes.
In iPad, in a container view controller, only viewcontroler.view is loaded.
Incident Identifier: EE102239-34D1-4BE7-8B52-41F74AB26203
CrashReporter Key: 2b11ea2a01ac5618e199ffc5a1e1f321600bb6a9
Hardware Model: iPad3,4
Version: ??? (???)
Code Type: ARM (Native)
Parent Process: launchd [1]
Date/Time: 2013-06-18 15:19:16.132 +0200
OS Version: iOS 6.1.3 (10B329)
Report Version: 104
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x00000000
Crashed Thread: 0
Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0 libobjc.A.dylib 0x3bab7070 prepareForMethodLookup + 20
1 libobjc.A.dylib 0x3bab6fb2 lookUpMethod + 42
2 libobjc.A.dylib 0x3bab6f7e _class_lookupMethodAndLoadCache3 + 14
3 libobjc.A.dylib 0x3bab6638 objc_msgSend_uncached + 24
4 QuartzCore 0x357f2a72 CA::Layer::contents_visibility_changed(CA::Transaction*, bool) + 50
5 QuartzCore 0x357f29de CA::Layer::mark_visible(CA::Transaction*, bool) + 190
6 QuartzCore 0x357f29b2 CA::Layer::mark_visible(CA::Transaction*, bool) + 146
7 QuartzCore 0x357f29b2 CA::Layer::mark_visible(CA::Transaction*, bool) + 146
8 QuartzCore 0x357f29b2 CA::Layer::mark_visible(CA::Transaction*, bool) + 146
9 QuartzCore 0x357f29b2 CA::Layer::mark_visible(CA::Transaction*, bool) + 146
10 QuartzCore 0x357f28d2 CA::Layer::update_removed_sublayer(CA::Transaction*, unsigned int) + 18
11 QuartzCore 0x357f255a CA::Layer::remove_sublayer(CA::Transaction*, CALayer*) + 130
12 QuartzCore 0x357f246a CA::Layer::remove_from_superlayer() + 34
13 UIKit 0x35a6e92c -[UIView(Hierarchy) removeFromSuperview] + 144
14 UIKit 0x35b857bc -[UIScrollView removeFromSuperview] + 60
15 MyApp 0x000bde8a -[iPadNavigationController vcAnimationDone] (iPadNavigationController.m:400)
16 UIKit 0x35a55ab6 -[UIViewAnimationState sendDelegateAnimationDidStop:finished:] + 154
17 UIKit 0x35aca8f8 -[UIViewAnimationState animationDidStop:finished:] + 44
18 QuartzCore 0x35801304 CA::Layer::run_animation_callbacks(void*) + 204
19 libdispatch.dylib 0x3bed55d8 _dispatch_client_callout + 20
20 libdispatch.dylib 0x3bed8e40 _dispatch_main_queue_callback_4CF + 224
21 CoreFoundation 0x33c051ac __CFRunLoopRun + 1284
22 CoreFoundation 0x33b78238 CFRunLoopRunSpecific + 352
23 CoreFoundation 0x33b780c4 CFRunLoopRunInMode + 100
24 GraphicsServices 0x37733336 GSEventRunModal + 70
25 UIKit 0x35a942b4 UIApplicationMain + 1116
A few line from the code (as asked),
previous = showing;
showing = [ vc retain ];
showing.view.frame = startFrameIn;
[ container addSubview:showing.view ];
CGContextRef context = UIGraphicsGetCurrentContext();
[ UIView beginAnimations:nil context:context ];
[ UIView setAnimationDelegate:self ];
[ UIView setAnimationDidStopSelector:#selector(vcAnimationDone) ];
[ UIView setAnimationCurve:UIViewAnimationCurveEaseOut ];
[ UIView setAnimationDuration:0.4 ];
previous.view.frame = endFrameOut;
showing.view.frame = detailFrame;
[ UIView commitAnimations ];
}
- (void) vcAnimationDone {
if ( previous != nil ) {
if (previous.view.superview != nil) {
[previous.view removeFromSuperview];
}
[ previous release ];
previous = nil;
}
A very probable reason is that you are overreleasing your scrollview or one of the views inside it.
Calling removeFromSuperview then deallocates the view instead of simply decreasing the retain count.
Actually, if you are still stuck with non-ARC project, Static Code Analysis is very useful for this kind of bug. Retain/release balancing issues are hard to pin down, and nearly impossible with incomplete method so I suggest you post the full method body if possible.
Thanks everyone for your answers, tips and tricks. However one thing I want share with you is the cause of the crash. I found that the crash was at different thread in different times. I had several views loaded with button pressing/menu in my iPad app. Some of the button pressing fetch data from web service. So I was bit confused to get the cuase of crash, animation, or url connection etc... I tried with enabled NSZombie objects, but it did not show any information.
Then I tried with Guard Malloc. This only runs in Simulator. And magically I found the code point of crash. I have function to convert a hex string into data. There I have line of code to make a C string null terminated. where I assigned 0 at the last index. and that makes the crash!
tmpCh[count] = 0;
I do not why, but probably it takes some time in the memory management procedure in iOS so it crash at different thread at different times. But with Guard malloc in Simulator, it always point out here and when I rewrite the code, the crash is gone.
/* Converts a hex string to bytes.
Precondition:
. The hex string can be separated by space or not.
. the string length without space or 0x, must be even. 2 symbols for one byte/char
. sample input: 23 3A F1 OR 233AF1
*/
+ (NSData *) dataFromHexString:(NSString*)hexString
{
if (hexString.length < 1) {
return nil;
}
char * tmpCh = (char *) malloc([hexString length] * sizeof(char));
int count = 0;
for (int k=0; k<hexString.length;k++) {
char c = [hexString characterAtIndex:k];
if (c == (char)0x20) { //skip space
continue;
}
if (c == '0') { // skip 0x
if(k+1 < hexString.length){
if ([hexString characterAtIndex:k+1] == 'x'
|| [hexString characterAtIndex:k+1] == 'X' )
{
k = k + 1;
continue;
}
}
}
tmpCh[count] = c;
count++;
}
tmpCh[count] = 0; // make null terminated string
if (count % 2) {
return nil;
}
NSString *temp = [[NSString alloc] initWithUTF8String:tmpCh];
free(tmpCh);
if ([temp length] % 2 != 0) {
return nil;
}
NSMutableData *result = [[NSMutableData alloc] init];
unsigned char byte;
char hexChars[3] = {0};
for (int i=0; i < (temp.length/2); i++) {
hexChars[0] = [temp characterAtIndex:i*2];
hexChars[1] = [temp characterAtIndex:i*2+1];
if (![Util isValidChar:hexChars[0]] || ![Util isValidChar:hexChars[1]]) {
return nil;
}
byte = strtol(hexChars, NULL, 16);
[result appendBytes:&byte length:1];
}
NSData * data = [NSData dataWithData:result];
[result release];
return data;
}