2012-02-02 13 views
5

मैं कुछ समय से एक परियोजना पर काम कर रहा हूं, और मैंने एआरसी को कूदने का फैसला किया। मैं कुछ कोड में आया जो हर बार बमबारी कर रहा था, और मैं जानना चाहता हूं कि क्यों। मैं इस स्निपेट के लिए नीचे को आसान बनाने में कामयाब रहे:एआरसी और मॉलोक: EXEC_BAD_ACCESS

typedef __strong id MYID; 

int main(int argc, char *argv[]) 
{ 
    MYID *arr = (MYID *) malloc(sizeof(MYID) * 4); 

    arr[0] = @"A";  // always get an EXEC_BAD ACCESS HERE 
    arr[1] = @"Test"; 
    arr[2] = @"Array"; 
    arr[3] = @"For"; 

    // uh oh, we need more memory 
    MYID *tmpArray = (MYID *) realloc(arr, sizeof(MYID) * 8); 
    assert(tmpArray != NULL); 

    arr = tmpArray; 

    arr[4] = @"StackOverflow"; // in my actual project, the EXEC_BAD_ACCESS occurs here 
    arr[5] = @"Is"; 
    arr[6] = @"This"; 
    arr[7] = @"Working?"; 

    for (int i = 0; i < 8; i++) { 
     NSLog(@"%@", arr[i]); 
    } 

    return 0; 
} 

मैं काफी यकीन है कि यहाँ क्या हो रहा है 4 विभिन्न परियोजनाओं में इस थक, नहीं कर रहा हूँ, और वे सभी असफल। क्या मेरे malloc कॉल में कुछ गड़बड़ है? कभी-कभी यह शून्य हो जाता है, और दूसरी बार यह एक सूचक देता है जिसे मैं एक्सेस नहीं कर सकता।

+0

टाइपपीफ क्यों? ऑब्जेक्ट पॉइंटर्स जो अन्यथा योग्य नहीं हैं उन्हें '__strong' माना जाता है। –

+0

क्योंकि वास्तविक प्रोजेक्ट में, 'MYID' एक स्ट्रक्चर का हिस्सा है (कोकोस 2 डी का सीसीसीएरे)। साथ ही, कोड स्वामित्व के लिए क्वालीफायर के बिना संकलित नहीं होगा, क्योंकि यह एक चयनकर्ता का हिस्सा नहीं है जहां मालिक 'स्वयं' हो सकता है। –

+0

मुझे यकीन नहीं है कि आपका क्या मतलब है "क्योंकि यह एक चयनकर्ता का हिस्सा नहीं है जहां मालिक 'स्वयं' हो सकता है। किसी विधि में आवंटित ऑब्जेक्ट का "स्वामी" स्टैक स्वयं होता है, न कि 'self' का मान। यह भी ध्यान रखें कि आप एआरसी के तहत सी संरचना में '__strong' (या' __weak') ऑब्जेक्ट पॉइंटर्स नहीं रख सकते हैं, आपको '__unsafe_unretained' का उपयोग करना होगा और स्मृति को स्पष्ट रूप से प्रबंधित करना होगा (उदाहरण के लिए कुछ गैर-एआरसी कोड या 'CFRetain()'/'CFRelease()')। –

उत्तर

13

दुर्घटना इसलिए है क्योंकि आप वस्तुओं की सी सरणी में malloc'd स्मृति कास्टिंग कर रहे हैं। जिस पल में आप स्लॉट में से किसी एक को असाइन करने का प्रयास करते हैं, एआरसी पिछले मूल्य को जारी करेगा, जो कचरा स्मृति होगी। शून्य स्मृति प्राप्त करने के लिए malloc() के बजाय calloc() का उपयोग करने का प्रयास करें और इसे काम करना चाहिए।

ध्यान रखें कि आपके realloc() कॉल भी नहीं किसी भी नए स्मृति कि आवंटित है शून्य भर जाएगा, इसलिए यदि आप realloc() तो जरूरत है आप चाहते हो सकता है एक अस्थायी void* सूचक है कि आप तो मैन्युअल रूप से अपने वस्तु को सौंपने से पहले शून्य को भरने का उपयोग करने के सरणी।

+3

डांग। सूक्ष्म। आपको इस उदाहरण में एआरसी का उपयोग करने के लिए वास्तव में/रिलीज/सी के बारे में बहुत कुछ पता होना चाहिए। – nielsbot

+0

धन्यवाद केविन, वह था। –

+0

@nielsbot: जब तक आप Obj-C से चिपके रहते हैं, आपको कोई समस्या नहीं होनी चाहिए। एआरसी के साथ मूल सी सामान (जैसे 'malloc() ') को गठबंधन करने की कोशिश करते समय इस तरह की चीज केवल तभी बढ़ जाती है। –

8

malloc फ़ंक्शन आवंटित स्मृति को शून्य नहीं करता है। स्मृति में यादृच्छिक कचरा हो सकता है।

Clang Automatic Reference Counting गाइड से, अनुभाग 4.2:

__strong वस्तुओं के लिए, नई pointee पहले बनाए रखा है; दूसरा, आभासी आदिम अर्थशास्त्र से भरा हुआ है; तीसरा, नया पॉइंटी मूलभूत अर्थशास्त्र के साथ लालू में संग्रहीत किया जाता है; और अंत में, पुराना पॉइंट जारी किया गया है।

तो शायद यहां क्या हो रहा है malloc यादृच्छिक गैर-शून्य मान वाले स्मृति को वापस कर रहा है। एआरसी किसी ऑब्जेक्ट को पॉइंटर के रूप में उस यादृच्छिक मान का उपयोग करने की कोशिश करता है और इसे छोड़ देता है, लेकिन यह मान्य ऑब्जेक्ट पॉइंटर नहीं है। दुर्घटना।