2012-06-08 20 views
7

यह कोड मुझे EXC_BAD_ACCESS देता है, क्यों?यह कोड EXC_BAD_ACCESS (IMP का उपयोग करके) क्यों देता है

NSMutableDictionary *d = [[NSMutableDictionary alloc] init]; 
IMP imp= [d methodForSelector:@selector(setObject:forKey:) ]; 
imp(d, @selector(setObject:forKey:), @"obj", @"key"); 

मैं अभी आईएमपी का उपयोग शुरू कर रहा हूं, firs कोशिश .. कोई भाग्य नहीं। निश्चित नहीं है कि मुझे त्रुटि क्यों मिलती है, अतीत में .. जब मुझे EXC_BAD_ACCESS मिला, तो संदेश कंसोल पर मुद्रित किया गया था, इस बार त्रुटि रेखा को हाइलाइट किया गया था।

कुछ नोट: एआरसी सक्षम किया गया है, XCode 4.3.2, परियोजना डे डिफ़ॉल्ट भाषा/संकलक के रूप में ऑब्जेक्टिव-सी ++ का उपयोग करता है, इस कोड को परियोजना के बहुत शुरुआत

धन्यवाद लोग पर है

+0

मैं पुन: पेश नहीं कर सकता। यदि आप इसे एक नई परियोजना में डालते हैं, तो क्या आपको अभी भी त्रुटि मिलती है? – Chuck

+0

हाँ, मुझे क्या मिला है ... एआरसी समस्या है। एआरसी सक्षम के साथ एक नया आईओएस प्रोजेक्ट बनाने का प्रयास करें। फिर कहीं भी कोड कॉपी और पेस्ट करें (मैंने इसे एप्लिकेशन में रखा है FinishLaunchingWithOptions :) – subzero

उत्तर

20

आपको फ़ंक्शन पॉइंटर को सही तरीके से डालना होगा या एआरसी नहीं जानता कि यह क्या करना है। आईएमपी एक सामान्य फ़ंक्शन पॉइंटर है जो एक आईडी, एक चयनकर्ता और अन्य की एक परिवर्तनीय संख्या, अपरिभाषित तर्क लेता है और एक आईडी देता है। विधि कार्यान्वयन जिसे आप कॉल करने का प्रयास कर रहे हैं, एक आईडी लेता है, एक चयनकर्ता के बाद दो आईडी पैरामीटर होते हैं और शून्य शून्य रिटर्न प्रकार होता है। आप नीचे दिए गए कोड को बदलकर इसे ठीक कर सकते हैं:

NSMutableDictionary* dict = [[NSMutableDictionary alloc] init]; 
void (*imp)(id, SEL, id, id) = (void(*)(id,SEL,id,id))[dict methodForSelector:@selector(setObject:forKey:)]; 
if(imp) imp(dict, @selector(setObject:forKey:), @"obj", @"key"); 

आपको हमेशा यह सुनिश्चित करना चाहिए कि आप वास्तव में, वापस आप इसे भिन्नता से पहले एक समारोह सूचक मिला के रूप में वह भी दुर्घटना होगा। उपरोक्त कोड एआरसी पर्यावरण में भी काम करेगा। साथ ही, जब आप एआरसी का उपयोग नहीं कर रहे हैं, तब भी आपको हमेशा अपने फ़ंक्शन पॉइंटर्स को आईएमपी की बजाय वास्तविक प्रोटोटाइप पर डालना चाहिए। आपको कभी भी आईएमपी का उपयोग नहीं करना चाहिए। अन्य जगहें जो प्रमुख मुद्दों का कारण बनती हैं, यदि विधि एक संरचना लौटाती है या यदि विधि फ्लोटिंग पॉइंट पैरामीटर लेती है, तो

अच्छी आदत: हमेशा अपने फ़ंक्शन पॉइंटर्स डालें या उनके लिए टाइपपीफ बनाएं यदि आपको फ़ंक्शन पॉइंटर सिंटैक्स जारिंग मिलती है ।

+0

धन्यवाद जेसन। यह एक आकर्षण के रूप में काम किया! प्रश्न: यह फ़्लोटिंग पॉइंट पैरामीटर के साथ structs या विधियों के साथ एक बड़ा मुद्दा क्यों होगा ?, अगर आप मुझे कुछ दस्तावेज़ में इंगित कर सकते हैं तो मैं खुश रहूंगा। मुझे बस "रनटाइम" विषय दिलचस्प लगता है। – subzero

+1

इसे सी में कार्यों के कॉलिंग सम्मेलन और पैरामीटर कैसे पारित किए जाते हैं। चूंकि संकलक 'स्वयं' और '_cmd' पैरामीटर के पीछे आईएमपी के मानकों के बारे में कुछ नहीं जानता है, इसलिए यह अन्य पैरामीटर को ढेर पर धक्का देगा और कॉल किए गए फ़ंक्शन को यह जानने के लिए उम्मीद करेगा कि उनके साथ क्या किया जाए। हालांकि, अगर बुलाया गया कार्य एक फ्लोट की अपेक्षा करता है, तो यह लगभग निश्चित रूप से जीपीआर (एआरएम के लिए) या अन्य एफपी-विशिष्ट रजिस्टर में दिखाई देगा, न कि स्टैक आदि पर। यह रिटर्न प्रकारों के लिए समान है, संरचनाओं को पॉइंटर्स से अलग तरीके से संभाला जाता है। –

1

समस्या यह है कि आईएमपी के पास "आईडी" का रिटर्न प्रकार है जो एआरसी प्रबंधन करने का प्रयास करेगा। आपको अपने फ़ंक्शन पॉइंटर को रिटर्न प्रकार का शून्य (आपके द्वारा बुलाए जाने वाले विधि के अनुरूप) रखने की आवश्यकता है:

NSMutableDictionary *d = [[NSMutableDictionary alloc] init]; 
    IMP imp= [d methodForSelector: @selector(setObject:forKey:)]; 
    void (*func)(__strong id,SEL,...) = (void (*)(__strong id, SEL, ...))imp; 
    func(d, @selector(setObject:forKey:), @"obj", @"key"); 
+0

'शून्य (*) (आईडी, एसईएल, ...) 'फ़ंक्शन पॉइंटर के लिए सही प्रकार नहीं है। यह 'शून्य (*) (आईडी, एसईएल, आईडी, आईडी)' है। हालांकि यह कुछ विशेष प्रकार ('आईडी') वाले कुछ आर्किटेक्चर पर इस विशेष मामले में काम कर सकता है, लेकिन यह सामान्य रूप से गलत है। – newacct

+0

यह वास्तव में काम किया। धन्यवाद। – Felipe