में उद्देश्य-सी लीकिंग में रिकर्सिव ब्लॉक, तो मैं रिकर्सिव ब्लॉक का उपयोग कर रहा हूं। मैं समझता हूं कि एक ब्लॉक के लिए रिकर्सिव होने के लिए इसे __block कीवर्ड से पहले होना चाहिए, और इसकी प्रतिलिपि बनाई जानी चाहिए ताकि इसे ढेर पर रखा जा सके। हालांकि, जब मैं ऐसा करता हूं, यह इंस्ट्रूमेंट्स में रिसाव के रूप में दिख रहा है। क्या कोई जानता है कि मैं इसके आसपास क्यों या कैसे प्राप्त कर सकता हूं?एआरसी
कृपया नीचे दिए गए कोड में ध्यान दें कि मुझे कई अन्य ब्लॉक के संदर्भ मिल गए हैं, लेकिन उनमें से कोई भी रिकर्सिव नहीं है।
__block NSDecimalNumber *(^ProcessElementStack)(LinkedList *, NSString *) = [^NSDecimalNumber *(LinkedList *cformula, NSString *function){
LinkedList *list = [[LinkedList alloc] init];
NSDictionary *dict;
FormulaType type;
while (cformula.count > 0) {
dict = cformula.pop;
type = [[dict objectForKey:@"type"] intValue];
if (type == formulaOperandOpenParen || type == formulaListOperand || type == formulaOpenParen) [list add:ProcessElementStack(cformula, [dict objectForKey:@"name"])];
else if (type == formulaField || type == formulaConstant) [list add:NumberForDict(dict)];
else if (type == formulaOperand) [list add:[dict objectForKey:@"name"]];
else if (type == formulaCloseParen) {
if (function){
if ([function isEqualToString:@"AVG("]) return Average(list);
if ([function isEqualToString:@"MIN("]) return Minimum(list);
if ([function isEqualToString:@"MAX("]) return Maximum(list);
if ([function isEqualToString:@"SQRT("]) return SquareRoot(list);
if ([function isEqualToString:@"ABS("]) return EvaluateStack(list).absoluteValue;
return EvaluateStack(list);
} else break;
}
}
return EvaluateStack(list);
} copy];
NSDecimalNumber *number = ProcessElementStack([formula copy], nil);
अद्यतन तो मेरे अपने अनुसंधान के क्षेत्र में मुझे पता चला है समस्या जाहिरा तौर पर अन्य ब्लॉक इस ब्लॉक का उपयोग करता है के संदर्भ के साथ क्या संबंध है कि। मैं कुछ इस तरह सरल करते हैं, यह रिसाव नहीं करता है:
__block void (^LeakingBlock)(int) = [^(int i){
i++;
if (i < 100) LeakingBlock(i);
} copy];
LeakingBlock(1);
हालांकि, अगर मैं इस में एक एक और ब्लॉक जोड़ने के लिए, यह रिसाव करता है:
void (^Log)(int) = ^(int i){
NSLog(@"log sub %i", i);
};
__block void (^LeakingBlock)(int) = [^(int i){
Log(i);
i++;
if (i < 100) LeakingBlock(i);
} copy];
LeakingBlock(1);
मैं __block का उपयोग कर की कोशिश की है लॉग() के लिए कीवर्ड और इसे कॉपी करने का भी प्रयास किया, लेकिन यह अभी भी लीक है। कोई विचार?
अद्यतन 2 मुझे रिसाव को रोकने के लिए एक रास्ता मिला, लेकिन यह थोड़ा कठिन है। यदि मैं पारित ब्लॉक को एक कमजोर आईडी में परिवर्तित करता हूं, और उसके बाद कमजोर आईडी को ब्लॉक प्रकार में डाल देता हूं, तो मैं रिसाव को रोक सकता हूं।
void (^Log)(int) = ^(int i){
NSLog(@"log sub %i", i);
};
__weak id WeakLogID = Log;
__block void (^LeakingBlock)(int) = [^(int i){
void (^WeakLog)(int) = WeakLogID;
WeakLog(i);
if (i < 100) LeakingBlock(++i);
} copy];
LeakingBlock(1);
निश्चित रूप से एक बेहतर तरीका है?
अपने शोध को साझा करने के लिए धन्यवाद, मैंने ब्लॉक की प्रतिलिपि बनाने के बारे में नहीं सुना है। हालांकि, ऐसा प्रतीत होता है कि एक हालिया एलएलवीएम इस ब्लॉक में दृढ़ता से कॉल "लीकिंगब्लॉक कैप्चरिंग" पर एक चेतावनी को उत्सर्जित करता है, जो एक चक्र को बनाए रखने की संभावना है।संकलक को प्रसन्न करने का एकमात्र तरीका यह है कि ब्लॉक के लिए एक अलग कमजोर पीआरटी का उपयोग कुछ हद तक आपके उत्तर के समान है, हालांकि इसके अनावश्यक रूप से पर्याप्त है कि मैं स्थानीय रूप से चेतावनी को ओवरराइड करने के लिए प्रेरित हूं। एक बार जब आप नवीनतम कंपाइलर आज़माते हैं तो मुझे अपना लेना देखने में दिलचस्पी होगी। –
@smallduck मूल रूप से, मैंने 'प्रतिलिपि' का उपयोग किया क्योंकि यह ब्लॉक को ढेर से ढेर तक कॉपी करने का कारण बनता है। थोड़ी देर के लिए जो ठीक काम करता था और मुझे कंपाइलर "रिकर्सिव" त्रुटि भी मिली। मैंने अपने कोड से 'कॉपी' हटा दी है (जैसा कि मेरे उत्तर में दिखाई देता है) और यह काम करता है (जबकि पहले मुझे 'EXC_BAD_ACCESS' मिल जाएगा। मुझे लगता है कि ऐप्पल ने' __block' कीवर्ड को बदल दिया है ताकि ढेर पर ब्लॉक बना सकें ढेर ... लेकिन यह सिर्फ एक अनुमान है। –
@smallduck सचमुच, मैंने रिकर्सन के लिए ब्लॉक का उपयोग छोड़ दिया है। हाँ, यह किया जा सकता है लेकिन यह थोड़ा अनावश्यक है और बहुत सारे नुकसान हैं। इसे समाप्त करना बहुत आसान है चक्र बनाए रखें (जो रिकर्सन के साथ वास्तव में खराब हो सकता है) और इसे पढ़ना मुश्किल हो जाता है। इसलिए आमतौर पर मैं रिकर्सन करने के लिए विधियों/कार्यों के साथ चिपक जाता हूं। –