Your example leaves a lot of variables to be questioned by any potential helper. For example: what if there's something funky with this unarchiver? Is memory being managed correctly?
I was able to reproduce the crash you're seeing, and can confirm it only occurs when -O3 is enabled, and not when e.g. None is selected for optimization. Here is a reduction of the crashing code that eliminates outside variables such as memory management of the coders, etc. Note the code below purposefully retains all objects to eliminate the possibility that the crash is related to an accidental over-release, or a side-effect of using ARC, as suggested by Andy in another answer:
typedef struct
{
NSInteger x;
NSInteger y;
}
BBPointI32;
- (void) testDecoding
{
NSString* myKey = @"Testing";
// First get an coder with bytes in it
NSMutableData* myData = [[NSMutableData data] retain];
NSKeyedArchiver* myCoder = [[NSKeyedArchiver alloc] initForWritingWithMutableData:myData];
BBPointI32 encodedStruct = {1234, 5678};
[myCoder encodeBytes:(const uint8_t *)&encodedStruct length:sizeof(encodedStruct) forKey:myKey];
[myCoder finishEncoding];
// Now decode it
BBPointI32 decodedStruct;
NSUInteger decodedLength = 0;
NSKeyedUnarchiver* myDecoder = [[NSKeyedUnarchiver alloc] initForReadingWithData:myData];
uint8_t* data = (uint8_t*)[myDecoder decodeBytesForKey:myKey returnedLength:&decodedLength];
decodedStruct = *(BBPointI32*)data;
NSLog(@"Got decoded struct with x = %ld, y = %ld, length = %lu", decodedStruct.x, decodedStruct.y, decodedLength);
}
- (void)applicationDidFinishLaunching:(UIApplication *)application {
NSLog(@"Testing decoding");
[self testDecoding];
}
I think this gives a more succinct description of the problem that anybody who wants to help can use as a basis for diving in. My hunch thus far is this is an optimization bug in LLVM 3.0, but maybe somebody else will have a better theory about what is going on.
A point that you didn't mention in your question, but which I notice in the crash on my device, is the failure is accompanied by mention of a EXC_ARM_DA_ALIGN error as the reason for the bad access exception. I Googled a blog post that seems to allude to the same symptoms and probably cause for crashing as you are seeing here:
http://www.galloway.me.uk/2010/10/arm-hacking-exc_arm_da_align-exception/
Indeed, by changing the line above
decodedStruct = *(BBPointI32*)data;
to
memcpy(&decodedStruct, data, sizeof(decodedStruct));
The crashing behavior seems to be alleviated and the code behaves as expected.
ldrd
. When I castdata
to aBBPointI32*
it assumed that this meant that the pointer was properly aligned, but it wasn't. So, instead of: m_value = (BBPointI32)data; I needed to use: memcpy(&m_value, data, length); – Agraffe