मैं इस दुर्घटना के पीछे कारणों को समझने की कोशिश कर रहा हूं कि ब्लॉकों का व्यवहार कैसे होता है। इस दुर्घटना को ट्रिगर करने के लिए मेरे पास वास्तव में एक साधारण वर्ग है।प्रेषण के साथ क्रैश
@implementation BlockCrashTest
- (void)doSomething
{
dispatch_queue_t queue = dispatch_queue_create("com.queue.test", DISPATCH_QUEUE_SERIAL);
__weak typeof(self) weakSelf = self;
dispatch_block_t block = ^{
__strong typeof(weakSelf) strongSelf = weakSelf;
dispatch_group_t group = dispatch_group_create();
dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC);
dispatch_group_enter(group);
[strongSelf performSomethingAsync:^{
dispatch_group_leave(group);
}];
if(dispatch_group_wait(group, time) != 0) {
NSLog(@"group already finished");
}
};
dispatch_async(queue, block);
}
- (void)performSomethingAsync:(void(^)(void))completion
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
sleep(5);
completion();
});
}
- (void)dealloc
{
NSLog(@"released object");
}
@end
अब, अगर मैं कक्षा का आवंटन और केवल विधि DoSomething इसे करने के लिए कहते हैं,
BlockCrashTest *someObject = [[BlockCrashTest alloc] init];
[someObject doSomething];
यह अपवाद के साथ दुर्घटनाओं, EXC_BAD_INSTRUCTION और निम्न स्टैक ट्रेस,
#0 0x000000011201119a in _dispatch_semaphore_dispose()
#1 0x0000000112013076 in _dispatch_dispose()
#2 0x0000000112026172 in -[OS_dispatch_object _xref_dispose]()
#3 0x000000010ef4c2fd in __29-[BlockCrashTest doSomething]_block_invoke at /Users/Sandeep/Desktop/Test Block Crash/Test Block Crash/ViewController.m:35
#4 0x0000000112005ef9 in _dispatch_call_block_and_release()
यदि मैं विधि को संशोधित करता हूं तो कुछ,, ऐसी है कि वह कमजोर का उपयोग नहीं करते लेकिन का उपयोग करता है स्वयं तो दुर्घटना नहीं होती है और तरीकों के रूप में उम्मीद निष्पादित करने के लिए लग रहे हैं
- (void)doSomething
{
dispatch_queue_t queue = dispatch_queue_create("com.queue.test", DISPATCH_QUEUE_SERIAL);
dispatch_block_t block = ^{
dispatch_group_t group = dispatch_group_create();
dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC);
dispatch_group_enter(group);
[self performSomethingAsync:^{
dispatch_group_leave(group);
}];
if(dispatch_group_wait(group, time) != 0) {
NSLog(@"group already finished");
}
};
dispatch_async(queue, block);
}
यह क्यों दुर्घटना करता है, मैं समझता हूँ कि ब्लॉक के अंदर कमजोर उपयोग कर रहा है यह सुनिश्चित करेगा कि ऑब्जेक्ट जारी होने पर विधि को नहीं कहा जाएगा और मैंने सोचा था कि कमजोर ब्लॉक के अंदर स्वयं का उपयोग करने से सुरक्षित है।
ऊपर कोड weakSelf साथ ठीक काम करता है, अगर मैं वस्तु BlockCrashTest को बनाए रखने और इसे करने के लिए विधि कॉल।
अगर कोई दुर्घटना के पीछे कारण बता सकता है और कोड के इन 3 अलग-अलग प्रकारों के साथ वास्तव में क्या होता है तो मैं वास्तव में खुश हूं कि एक दुर्घटना और अन्य ठीक काम करने लगते हैं।
नोट: यह एक ही रास्ता या धागा, Objective-C crash on __destroy_helper_block_ में सूचीबद्ध दुर्घटना के अन्य संबंधित है। मैं ऊपर दिए गए कोड के साथ सटीक उसी स्टैक निशान को पुन: पेश करने में सक्षम हूं।
क्या आप मुझे ब्लॉक के अंदर स्वयं का उपयोग करने पर भी एक संकेत दे सकते हैं कि यह क्रैश क्यों नहीं होता है? क्या यह केवल इसलिए है कि ब्लॉक स्वयं को बरकरार रखता है? – Sandeep
@ जनरेटरऑफोन - क्योंकि 'स्वयं' की उपस्थिति ब्लॉक के अंदर मजबूत संदर्भ स्थापित करती है, जिसे तब तक हल नहीं किया जाता है जब तक कि ब्लॉक निष्पादित नहीं हो जाता है। इस प्रकार 'कमजोर' 'शून्य 'नहीं है और' मजबूत स्वयं '' शून्य' नहीं है। इस प्रकार, 'execSomethingAsync' में आपका पूरा होने वाले हैंडलर ब्लॉक को कॉल किया जा रहा है, यह सुनिश्चित करना कि "एंटर" अब "छोड़ें" द्वारा संतुलित है। लेकिन यदि आप चाहते थे कि ब्लॉक वस्तु को बरकरार रखे, तो आप स्पष्ट रूप से कमजोर/मजबूत स्वयं नृत्य के माध्यम से नहीं गए होंगे। – Rob
यह अच्छी व्याख्या है। इसलिए, मेरे पास कुछ ऑटोरेलेज्ड ऑब्जेक्ट हो सकता है जो अभी भी कुछ लंबी एसिंक्रोनस कॉल कर सकता है और यदि मैं कमजोर/मजबूत उपयोग करने के बजाय स्वयं का उपयोग करता हूं तो भी आसपास हो सकता है। यद्यपि यदि वस्तु स्वयं को बरकरार रखती है, तो यह कमजोर/मजबूत होने का अर्थ है, क्या यह इस बात का सारांश है? – Sandeep