2011-07-06 25 views
9

मेरे ऐप में मैं चूक डेटाबेस के लिए कई तार लिखते हैं, इस तरह:NSUserDefaults एक deallocated स्ट्रिंग क्यों देता है? (अद्यतन # 2)

[[NSUserDefaults standardUserDefaults] setObject:@"Hi" forKey:@"GREETING"]; 

मेरे एप्लिकेशन का जीवन काल के दौरान इस पर कई बार फोन, तो मैं ऊपर में किसी त्रुटि के साथ समाप्त और अधिक विस्तार में

NSString *val = [[NSUserDefaults standardUserDefaults] objectForKey:@"someKey"]; 

यहाँ: इस कोड पर कदम के बाद सांत्वना crash

आप मैं बिल्कुल +०१२३९७०६५९२४ लिए विधि कॉल के साथ लाइन पर एक ब्रेकपाइंट देख सकते हैं जैसाके। कदम उठाने के बाद, दुर्घटना पहले से ही होती है! val में जो भी है उसे पढ़ने का कोई मौका नहीं है। इसे हटा दिया गया है!

यह किसी भी स्ट्रिंग के साथ होता है जिसे मैंने एनएसयूसर डीफॉल्ट में रखा है, और मैं स्मृति प्रबंधन के साथ कुछ भी गलत नहीं कर रहा हूं। लीक्स इंस्ट्रूमेंट क्लेंग स्टेटिक विश्लेषक के परिणाम के समान ही सही है।

कंसोल त्रुटि:

*** -[CFString retain]: message sent to deallocated instance 0x610ba10 

दुर्घटना के बाद डीबगर में स्टैक ट्रेस के शीर्ष पर: (शीर्ष पंक्ति पढ़ता अग्रेषण)

stacktrace

मशीन कोड प्रतीक:

arm code

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

मैंने सोचा कि शायद एक स्मृति रिसाव है जो सभी रैम खाती है। लेकिन यह एक बड़ी विकास मशीन के साथ-साथ आईपैड पर भी होता है। दृश्य को दो बार रिलीज़ और पुनः लोड करें और एनएसयूसर डीफॉल्ट में यह दोष है।

बस यह मेरी गलती नहीं है सुनिश्चित करने के लिए, मैं अपने NSUserDefaults कुछ इस तरह करने के लिए कोड लिखने को फिर से लिखा है:

[[NSUserDefaults standardUserDefaults] setObject:[theString copy] forKey:key]; 

लेकिन फिर भी, मैं NSUserDefaults से पुनः आवंटित की जाती स्ट्रिंग उदाहरणों हो रही के साथ खत्म! सिम्युलेटर और डिवाइस पर! इसके अलावा, उन तार का उपयोग करने के लिए मैं कोशिश से कुछ डिफ़ॉल्ट के रूप में जब + (void)initialize

NSDictionary *preSettings = [[NSDictionary alloc] initWithObjectsAndKeys: 
@"Hollywood", @"defaultCity", 
nil]; 
[[NSUserDefaults standardUserDefaults] registerDefaults:preSettings]; 

में आवेदन आरंभ इसलिए भले ही मैं कुंजी "@ defaultCity के लिए इस स्ट्रिंग में परिवर्तन नहीं करते लिखा गया है और मैं के बाद इसे उपयोग करना चाहते थोड़ी देर (जब मैंने उस वसा दृश्य को दो बार फिर से लोड किया), तो मुझे एनएसयूसर डीफॉल्ट से एक विलुप्त उदाहरण मिल गया।

मैंने पूरी चीज को फिर से शुरू करने की कोशिश की, मैन्युअल रूप से ऐप डिलीगेट में अपनी विधि को कॉल करने का प्रयास किया जो डिफ़ॉल्ट शब्दकोश को पंजीकृत करता है NSUserDefaults के साथ। कुछ भी मदद नहीं करता है।

मैंने 100% सुनिश्चित किया है कि वें ईर कोई स्मृति रिसाव नहीं है (लीक उपकरण के साथ अत्यधिक परीक्षण किया जाता है)। मुझे यह नहीं मिलता है कि ऐसा क्यों होता है।मैंने बिना किसी सफलता के एनएसयूसर डीफॉल्ट (जो कि बेवकूफ होगा) को लिखने से पहले 5 बार उन तारों को बनाए रखने की कोशिश की थी।

विचार?


समस्या हल हो गई!

NSUserDefaults द्वारा लौटे तारों में से एक को बनाए रखने वाली संपत्ति को सौंपा गया था। मैं के सामने self. जोड़ना भूल गया जिसके परिणामस्वरूप उस स्ट्रिंग को ओवर-रिलीज़ किया गया था जब दृश्य को हटा दिया गया था।

अजीब हालांकि, कि मैं उस दृश्य को लोड, नष्ट, लोड, नष्ट करने में सक्षम था। और फिर यह NSUserDefaults से किसी भी स्ट्रिंग को पढ़ने के पहले प्रयास पर हुआ। यह एक डेलोकॉटेड स्ट्रिंग की तरह है जो डिफ़ॉल्ट शब्दकोश या डिफ़ॉल्ट डेटाबेस के माध्यम से प्रचार करता है और एनएसयूसर डीफॉल्ट और एनएस डिक्शनरी एल्गोरिदम को नाटकीय रूप से चलाते हुए सब कुछ नीचे आँसू देता है।

उस त्रुटि को ठीक करने के बाद सब ठीक काम किया। NSUserDefaults में अन्य सभी तारों तक पहुंच सहित। काम करता है, लेकिन फिर भी एक रहस्य यह कैसे भूल गया कि self. का इतना बड़ा प्रभाव पड़ा।

इस समस्या को हल करने में आपकी सहायता करने वाले सभी को धन्यवाद। आपने मुझे दिल के दौरे से बचाया। मैं इसके बहुत करीब था। खैर, अब कुछ नई चीजें खरीदनी होंगी ... मेरा कार्यालय गोवाल्ड हमले के बाद स्टार गेट रूम की तरह दिखता है।

+0

क्या आप NSUserDefaults में स्ट्रिंग को सहेजने के लिए अपना कोड पोस्ट कर सकते हैं? – iMOBDEV

+0

हां, कृपया मेरा अद्यतन उत्तर देखें। – openfrog

उत्तर

10

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

p = [NSAutoreleasePool new]; 
NSString *val = [[NSUserDefaults standardUserDefaults] objectForKey:@"someKey"]; 
[val release]; 
[p drain]; 
val = [[NSUserDefaults standardUserDefaults] objectForKey:@"someKey"]; 

आप वैल में एक deallocated स्ट्रिंग संदर्भ में पहुंचते हैं। आप अपने कोड में val के साथ क्या कर रहे हैं?


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


[[NSUserDefaults standardUserDefaults] setObject:[theString copy] forKey:key]; 

आपको लगता है कि कोड में theString की प्रतिलिपि लीक कर रहे हैं।

I've made 100% sure that there are no memory leaks (tested excessively with the Leaks instrument). I don't get it why this happens. I also tried to retain those strings 5 times before I write them to NSUserDefaults (which would be stupid anyways), with no success.

लीक साधन न 100% सही है, और न ही यह सब रिसाव का पता लगाने कर सकते हैं। यदि कोई ऑब्जेक्ट कहीं भी का संदर्भ है, तो इसे रिसाव के रूप में नहीं माना जाता है।

I thought maybe there is a memory leak that eats up all the RAM. But this happens on a big development machine as well as on the iPad. Release and reload the view two times and NSUserDefault has this defect.

चक का सिद्धांत सबसे अधिक सही है; सबसे अधिक संभावना है, आप की तरह कुछ है:

आईडी foo = ... किसी वस्तु ... [foo रिहाई]; ... इस तरह के NSUserDefaults साथ कुछ है कि यह एक वस्तु आवंटित करने के लिए होता है करना जहां अब-झूलते foo अंक के लिए ... [foo रिहाई]; .... ओह; अब उपयोगकर्ता चूक में वस्तु पुनः आवंटित की जाती किया गया है

आसान यह पता लगाने की; एक्सकोड में रन पैनल के डायग्नोस्टिक टैब में "मॉलोक स्टैक लॉगिंग" चालू करें। फिर, जब दुर्घटना होती है, तो info malloc <address of bad thing> करें और उस पते पर हुई सभी मॉलोक/मुक्त घटनाओं को हटा दिया जाएगा। सबसे अधिक संभावना है कि आप कुछ ऐसा देखेंगे:

- malloc 
- free 
.... repeated some # of times .... 
- malloc of some object that you create 
- free of same 
- malloc of a string by NSUserDefaults 
- [inadvertent] free of same 
+2

NSUserDefaults स्ट्रिंग भी एक लटकते सूचक द्वारा अतिरंजित हो सकता है। यदि एक ऑटोरेलेज्ड ऑब्जेक्ट को उस स्थान पर असाइन किया जा रहा है जिसे बनाए रखा जाना चाहिए, और NSUserDefaults स्ट्रिंग को इसके स्थान पर आवंटित किया जा रहा है, जब हटाए गए ऑब्जेक्ट का "स्वामी" इसे रिलीज़ करने का प्रयास करता है, तो यह इसके बजाय इस स्ट्रिंग को रिलीज़ करेगा। – Chuck

+0

कृपया मेरा अद्यतन प्रश्न देखें। मैं autoreleased तार के साथ एक बहुत काम करते हैं, लेकिन यह बहुत ज्यादा नहीं भावना है कि यह हर स्ट्रिंग मैं NSUserDefaults में और केवल को छोड़ता है और दो बार मेरे विचार पुन: लोड के बाद डाल के साथ क्या हो रहा है बनाता है। – openfrog

+0

इसके अलावा, मैंने कोशिश की एक और चीज NSUserDefaults को जोड़ने से पहले तारों को स्पष्ट रूप से बनाए रखा था। कुछ भी मदद नहीं की। – openfrog

0

आप स्ट्रिंग को बनाए रखने का प्रयास कहां कर रहे हैं? NSUserDefaults एक ऑटोरेलेज्ड NSString देता है। क्या यह संभव है कि आप इसके साथ कुछ भी न करें जब तक कि ऑटोरेलीज पूल ने इसे साफ़ नहीं किया हो?

+0

नहीं, मैंने NSUserDefaults से वैल पढ़ा है और यह पहले से ही एक अस्वीकृत उदाहरण देता है! यही समस्या है। एनएसएलओजी सीधे अगली पंक्ति में चल रहा है। लौटाई गई स्ट्रिंग को हटा दिया गया है। – openfrog

+1

@openfrog - NSLog लाइन साबित नहीं होता कि वापस आ वस्तु पुनः आवंटित की जाती है, यह केवल साबित होता है कि यह एक ही पते पर है। स्मृति को किसी अन्य वस्तु के लिए पुन: उपयोग किया जा सकता था। – highlycaffeinated

+0

गंभीरता से, इसे ऑब्जेक्ट से प्राप्त करने के तुरंत बाद इसे हटा दिया जाता है ForKey :! मैं ब्रेकपॉइंट के साथ वैल के मूल्य का भी निरीक्षण नहीं कर सकता। ऑब्जेक्ट को कॉल करने के बाद फोर्के क्रैश पहले से ही दूसरे स्थान पर होता है जहां डीबगर लौटा हुआ मूल्य पढ़ना चाहता है, सीधे उस विधि कॉल से! – openfrog

2

यदि आपके एप्लिकेशन को वर्तमान विधि के दायरे से बाहर val का संदर्भ बनाए रखने की आवश्यकता है, तो आपको इसे retain भी करना होगा। यदि आप नहीं करते हैं, तो इसे एक्सेस करने का प्रयास करने से पहले इसे ऑटोरेलेज्ड हो सकता है।

+0

नहीं, मैंने NSUserDefaults से वैल पढ़ा है और यह पहले से ही एक आवंटित उदाहरण देता है! यही समस्या है। – openfrog

+0

@openfrog क्या कंसोल संदेश उत्पन्न करने वाले कोड की रेखा तुरंत 'objectForKey:' कॉल का पालन करती है? यदि आप संदर्भ प्राप्त करने के बीच विचलित होने के बजाय और संदर्भ का उपयोग करने का प्रयास करने के बजाय, यह पहले से ही अस्वीकार कर दिया गया था, तो मुझे आश्चर्य होगा। – highlycaffeinated

+0

गंभीरता से, इसे ऑब्जेक्ट से प्राप्त करने के तुरंत बाद इसे हटा दिया जाता है ForKey :! मैं ब्रेकपॉइंट के साथ वैल के मूल्य का भी निरीक्षण नहीं कर सकता। ऑब्जेक्ट को कॉल करने के बाद फोर्के क्रैश पहले से ही दूसरे स्थान पर होता है जहां डीबगर लौटा हुआ मूल्य पढ़ना चाहता है। – openfrog

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