2015-10-25 6 views
7

मैं मैदान में अपने कई उपयोगकर्ताओं द्वारा रिपोर्ट की गई एक क्रैशिंग बग डीबग करने का प्रयास कर रहा हूं। सभी मुझे एक ही ढेर दिखाने:आईओएस 9 .1 में dispatch_async पर एक SIGABRT को ट्रिगर कर सकता है?

Exception Type: EXC_CRASH (SIGABRT) 
Exception Codes: 0x0000000000000000, 0x0000000000000000 
Exception Note: EXC_CORPSE_NOTIFY 
Triggered by Thread: 8 
OS Version:   iOS 9.1 (13B143) 
Code Type:   ARM (Native) 

0 libsystem_kernel.dylib   0x392ccc84 0x392b8000 + 85124 
1 libsystem_pthread.dylib   0x39370732 0x3936c000 + 18226 
2 libsystem_c.dylib    0x39264f9a 0x3921a000 + 307098 
3 libsystem_c.dylib    0x39264f2c 0x3921a000 + 306988 
4 libsystem_c.dylib    0x392447ea 0x3921a000 + 174058 
5 MyApp       0x000cb3e0 __69-[MyDataManager myMethod:]_block_invoke (MyDataManager.m:2367) 

लाइन 2367 बस है:

2363: BOOL success = [db executeUpdate:@"INSERT INTO table (id, content) VALUES (?, ?)", message.remoteId, message.content]; 
2364: assert(success); 
2365: DebugLog(@"DB Results %d", success); 
2366: 
2367: dispatch_async(dispatch_get_main_queue(), ^{ 
2368:  [self cleanupMethod:args]; 
2369: }); 

जबकि वहाँ निश्चित रूप से है कि ब्लॉक के भीतर कोड है, यह केवल 1 लाइन लंबी है, और है कि कोड निष्पादित करने के लिए प्रकट नहीं होता है इस ढेर पर अन्यथा मैं cleanupMethodmyMethod से ऊपर देखता हूं।

संपादित करें: आप इसे देख सकते हैं, dispatch_async से ठीक पहले, एक जोर है! मैंने मूल रूप से सोचा था कि यह दुर्घटना जोरदार थी। लेकिन रेखा संख्याओं का मिलान कभी नहीं हुआ - जोर से कई लाइनें ऊपर थीं (लाइन 2364, 2367 नहीं) - और जब मैंने इसे और परीक्षण किया, तो मैंने देखा कि अगर जोर ट्रिगर होता है, तो मेरे ढेर में _block_invoke शामिल नहीं होगा myMethod को कॉल के अंत में जोड़ा जा सकता है।

क्या कोई सुझाव दे सकता है कि dispatch_async इस व्यवहार को कैसे ट्रिगर कर सकता है? इसके अलावा, क्या libsystem_c.dylib में ऐप्पल के कोड का प्रतीक होने का कोई तरीका है? libsystem_c.dylib की

बाइनरी छवि:

0x3921a000 - 0x3927efff libsystem_c.dylib armv7 <0b5d65608e6f38448cd207fbd748d372> /usr/lib/system/libsystem_c.dylib 

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

+ (MyDataManager *)mainStore { 
    static dispatch_once_t once; 
    static id sharedInstance; 
    dispatch_once(&once, ^{ 
     sharedInstance = [[self alloc] init]; 
    }); 

    return sharedInstance; 
} 

मैं वस्तु के परिणामों को समझने जब मेरे cleanupMethod:args विधि कहा जाता है पुनः आवंटित की जाती किया जा रहा ... लेकिन मैं सोचा मेरी वैश्विक सिंगलटन हमेशा के आसपास है और इस तरह हमेशा के लिए सुरक्षित हो जाएगा था मेरे कोड में जिस तरह से मैं कॉल करता हूं? मैं फिर से चक्रों को बरकरार रखने के बारे में चिंतित नहीं हूं, यह एक वैश्विक सिंगलटन माना जाता है।

क्या यह कोड नमूना ठीक है?

@interface MyDataManager 
@end 

@implementation MyDataManager 

+ (MyDataManager *)mainStore { 
    static dispatch_once_t once; 
    static id sharedInstance; 
    dispatch_once(&once, ^{ 
     sharedInstance = [[self alloc] init]; 
    }); 

    return sharedInstance; 
} 

- (void)myMethod { 
    NSDictionary *args = @{...} 
    ... 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     [self cleanupMethod:args]; 
    }); 
} 

- (void)cleanupMethod:(id)args { 
    ... 
} 

@end 

@interface MyViewController : UIViewController 
@end 

@implementation MyViewController 

- (void)viewDidLoad { 
    [super viewDidLoad]; 
    [[MyDataManager sharedInstance] myMethod]; 
} 

@end 
+0

यदि आप ब्लॉक के सामग्रियों को शामिल करने के लिए अपना प्रश्न संपादित करते हैं, या कम से कम कुछ पंक्तियां MyDataManager.m के लाइन 2367 के बाद संपादित करती हैं। –

+0

@rob mayoff हो गया! – esilver

+1

लगता है कि आपके 'स्वयं' को हटा दिया गया है जब ब्लॉक ब्लॉक –

उत्तर

2

ऐसा लगता है कि समस्या, self को मजबूत संदर्भ है, जो आपके अनुप्रयोग क्रैश में है जाहिरा तौर पर जब self कि पुनः आवंटित की जाती किया गया था बुला।

__weak typeof(self)weakSelf = self; 
dispatch_async(dispatch_get_main_queue(), ^{ 
    [weakSelf cleanupMethod:args]; 
}); 

कुछ कह सकते हैं कि आप यहाँ के रूप में अच्छी तरह से __strong typeof(weakSelf)strongSelf = weakSelf; उपयोग करने के लिए, बनाने के लिए होगा: इस कोड को एक नया वेरिएबल कि self करने के लिए एक कमजोर संदर्भ स्टोर करने के लिए जा रहा है, जो समस्या का समाधान किया कर देगा मजबूत संदर्भ चक्र से बचने के लिए कमजोर संदर्भ का एक मजबूत संदर्भ, लेकिन self जीवित रखने के लिए, लेकिन मैं इसे यहां नहीं करना चाहूंगा और यदि nil ब्लॉक के निष्पादन के समय होगा - nil पर संदेश पूरी तरह से हैं उद्देश्य-सी में ठीक है, तो कुछ भी नहीं होगा।

प्लस क्या होता है से पहले लाइन

0x000cb3e0 __69-[MyDataManager myMethod:]_block_invoke (MyDataManager.m:2367) 

निश्चित रूप से एक समस्या का निदान करने में मदद मिलेगी की स्टैक ट्रेस।

संपादित करें: ठीक है, आप अपनी साझा ऑब्जेक्ट तक पहुंचने पर कक्षा विधि mainStore का उपयोग नहीं कर रहे हैं। शायद यह मुद्दा है।

+0

1. कृपया बताएं कि आप एक कमजोर चर को संदेश भेजने का विचार क्यों करते हैं, जब तक कि आप सुनिश्चित न हों कि किसी और के पास एक मजबूत संदर्भ है (जिस स्थिति में कमजोर संदर्भ का उपयोग बकवास है)। 2. myMethod कॉल स्टैक पर नहीं है। यह संदेश के अंदर एक ब्लॉक है (संभवतः ब्लॉक कॉलिंग क्लीनअप विधि)। – gnasher729

+0

1. ठीक उसी स्थिति के कारण ओपी है। कमजोर संदर्भ में संदेश भेजने के बाद ऐप क्रैश नहीं होगा। 2. हां, आप इस बारे में सही हैं, मुझे नाम अंतर दिखाई नहीं दिया। – Soberman

+0

@ सोबरमैन आपके विचारों के लिए यहां बहुत बहुत धन्यवाद! मैंने अपने कोड के बारे में अधिक जानकारी जोड़ दी है - यह मुझे स्पष्ट नहीं है कि यह एक मजबूत/कमजोर रेफरी मुद्दा है। क्या आप मेरे विस्तारित प्रश्न और एलएमके पर एक नज़र डाल सकते हैं यदि आपको लगता है कि यह अभी भी अपराधी हो सकता है? धन्यवाद! – esilver

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