2011-10-11 10 views
8

द्वारा दिया अपसंदर्भन जब एप्पल LLVM संकलक 3.0 का उपयोग कर रहा NSCoder साथ एक असामान्य आनेवाला पाया और -O3 साथ संकलित किया है। यह केवल उपकरणों पर दुर्घटनाग्रस्त है। मैंने आईओएस 4 चलाने वाले आईफोन 4 का परीक्षण किया है, एक आईपैड 2 आईओएस 5 चला रहा है और एक आईपैड 1 आईओएस चला रहा है 4. सभी क्रैश समान रूप से। यहाँ कोड के प्रासंगिक अनुभाग है:iOS पर क्रैश डिवाइस जब एक सूचक NSCoder के decodeBytesForKey

-(id)initWithCoder:(NSCoder*)decoder 
{ 
    if (![super init]) 
    { 
     return nil; 
    } 

    NSUInteger length = 0; 

    uint8_t* data = (uint8_t*)[decoder decodeBytesForKey:BBKey returnedLength:&length]; 

    m_value = *(BBPointI32*)data; 

    return self; 
} 

और यहाँ क्या एक BBPointI32 है:

typedef struct 
{ 
    NSInteger x; 
    NSInteger y; 
} 
BBPointI32; 

EXC_BAD_ACCESS होता है जब data dereferenced है। यह एक शून्य सूचक समस्या है। अगर मैं जीडीबी संलग्न करता हूं, तो मैं देख सकता हूं कि लंबाई 8 है, आकार (बीबीपीओटीआईआई) भी 8 है और डेटा सही है।

ldrd r2, r3, [r0] 

कौन सा ठीक लग रहा है:

अगर मैं disassembly को देखो, दुर्घटना पर हो रहा है। आर 0 में 0xb546e है, जो data का पता है। जब मैं उस स्मृति का निरीक्षण करता हूं, तो मैं देख सकता हूं कि इसमें डेटा शामिल है। रुचि रखने वाले किसी भी व्यक्ति के लिए, आर 2 में 72 (सुनिश्चित नहीं है कि यह क्या है) और आर 3 में 8 (संभवतः length का मान) है।

क्या कोई इस मुद्दे पर कुछ प्रकाश डाल सकता है?

उत्तर

10

ldrd पते को 8-बाइट गठबंधन करने की आवश्यकता है। * (BBPointI32 *) डेटा idiom सुरक्षित नहीं है क्योंकि डेटा 8-बाइट गठबंधन नहीं है। इसके बजाय संरचना में बाइट्स प्राप्त करने के लिए memcpy का प्रयोग करें।

+0

धन्यवाद, यह जगह है। समस्या * 'ldrd' का उपयोग करने के संकलक के निर्णय से संबंधित थी। जब मैंने 'बीबीपीओटीआई 32 *' को 'डेटा' डाला तो यह माना जाता था कि इसका मतलब था कि सूचक सही ढंग से गठबंधन था, लेकिन ऐसा नहीं था। तो, इसके बजाय: m_value = * (BBPointI32 *) डेटा; मुझे उपयोग करने की आवश्यकता है: memcpy (& m_value, डेटा, लंबाई); –

+0

@biorhythmist .. सिर्फ एक उल्लसित twitterrer नहीं :) – ohhorob

+0

मैं कुछ बहुत समान अनुभव कर रहा हूँ। आईपैड 3 पर होता है, और _not_ आईपैड 2 पर होता है! –

4

क्या आप एआरसी का उपयोग कर रहे हैं? यदि ऐसा है, तो मेरा मानना ​​है कि मुद्दा यह है कि decodeBytesForKey: कॉल के बाद संकलक decoder को रिलीज़ करने के लिए स्वतंत्र है (इसलिए बफर जारी करना जिस पर वापसी मूल्य इंगित किया गया है)।

यह वही interior pointer issue garbage collection has है। आप CFRetain/CFRelease अपने डिकोडर को अपने जीवनकाल का विस्तार करने के लिए कर सकते हैं, या फिर उस बिंदु तक इसे जीवित रखने के लिए विधि में [decoder self] जोड़ें।

मुझे लगता है आप भी __attribute__((objc_precise_lifetime)) साथ decoder व्याख्या से इस समस्या को हल करने में सक्षम हो सकता है, लेकिन that attribute की मेरी समझ में कुछ हद तक धुंधला है।

3

आपका उदाहरण किसी भी संभावित सहायक द्वारा पूछे जाने वाले कई चर छोड़ देता है। उदाहरण के लिए: अगर इस अनारक के साथ कुछ गड़बड़ है तो क्या होगा? क्या स्मृति सही तरीके से प्रबंधित की जा रही है?

मैं जो क्रैश आप देख रहा हूं उसे पुन: पेश करने में सक्षम था, और यह पुष्टि कर सकता है कि -O3 सक्षम होने पर ही नहीं होता है, और जब नहीं। अनुकूलन के लिए कोई भी नहीं चुना गया है। यहां क्रैशिंग कोड में कमी आई है जो कोडर के मेमोरी मैनेजमेंट जैसे बाह्य चर को समाप्त करता है। ध्यान दें कि नीचे दिए गए कोड उद्देश्य से सभी ऑब्जेक्ट्स को बरकरार रखते हैं ताकि दुर्घटनाग्रस्त ओवर-रिलीज से संबंधित हो या एक साइड- के रूप में एक और उत्तर में एंडी ने सुझाव दिया, एआरसी का उपयोग करने का प्रभाव:।

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]; 
} 

मैं इस समस्या यह है कि किसी को भी, जो मदद करना चाहता है में गोताखोरी के लिए एक आधार के रूप में उपयोग कर सकते हैं की एक और अधिक संक्षिप्त विवरण देता है लगता है मेरे कूबड़ अब तक क्या यह एलएलवीएम 3.0 में एक अनुकूलन बग है, लेकिन हो सकता है कि किसी और के पास क्या हो रहा है इसके बारे में एक बेहतर सिद्धांत होगा।

एक बिंदु जिस पर आपने अपने प्रश्न में उल्लेख नहीं किया है, लेकिन जो कि मैंने अपने डिवाइस पर दुर्घटना में नोटिस किया है, विफलता के साथ EXC_ARM_DA_ALIGN त्रुटि का उल्लेख खराब पहुंच अपवाद के कारण के रूप में है।मैं एक ब्लॉग पोस्ट को एक ही लक्षण का उल्लेख करने के लिए और शायद आप के रूप में दुर्घटनाग्रस्त के लिए पैदा कर रहा है Google पर यहाँ देख रहे हैं:

को

http://www.galloway.me.uk/2010/10/arm-hacking-exc_arm_da_align-exception/

दरअसल,

decodedStruct = *(BBPointI32*)data; 

ऊपर लाइन बदलकर

memcpy(&decodedStruct, data, sizeof(decodedStruct)); 

क्रैशिंग व्यवहार को कम किया जा रहा है और कोड अपेक्षित व्यवहार करता है।

+0

मैंने अपने अंत में EXC_ARM_DA_ALIGN नहीं देखा, लेकिन हाँ, यह परिवर्तन मैंने भी किया है। आपकी सहायता के लिए धन्यवाद. –

1

मुझे यह थ्रेड मिला, "EXC_ARM_DA_ALIGN" और "EXC_BAD_ACCESS" googling। अन्य उत्तरों में से कोई भी मेरी मदद नहीं करता, क्योंकि यह त्रुटि अपेक्षाकृत सरल की वजह से बढ़ी है। मैंने लिखा था:

theArray = [[NSArray alloc] initWithObjects:@"first", @"second", @"third", 
         @"fourth", @"fifth", "sixth", nil]; 

यानी मैंने स्ट्रिंग अक्षर के सामने @ को छोड़ दिया था। त्रुटि को हल करने में इसे वापस रखकर।

+0

लॉल - मैंने बस इसे ट्रैक करने के लिए 2 घंटे बिताए। समाधान पोस्ट करने के लिए धन्यवाद। – wufoo

संबंधित मुद्दे