2016-11-03 4 views
6

मैं हर्ब सुतर की CppCon 2016 बात है, जिसमें उन्होंने एक उदाहरण around 37 minutes in दिया था, कुछ इस तरह देखा जा रहा है:सी ++ में कॉलबैक नरक क्या है और यह स्मृति को रिसाव क्यों करेगा?

void f(shared_ptr<T> & ptr) 
{ 
    obj.on_draw([=]() { ... } 
} 

इसके बाद वे कहते हैं,

मैंने सुना है यह कॉलबैक नरक बुलाया , जहां आप कॉलबैक पंजीकृत करते हैं और में इसका मजबूत मालिक होता है - यह एक कचरा-एकत्रित सूचक होता है लेकिन यह एक मजबूत मालिक है - लेकिन फिर आप इसे कभी भी छुटकारा नहीं पाते हैं और यह बस हमेशा के लिए संग्रहीत है और अब वस्तु कभी नहीं चली जाएगी।

तो वह कह रहा है कि इसे कॉलबैक नरक कहा जाता है और यह वस्तुओं को रिसाव करेगा। लेकिन मुझे समझ में नहीं आता कि इस कोड के साथ क्या गलत है और यह रिसाव क्यों होगा। क्या कोई मुझे यह समझा सकता है?

मैंने स्टैक ओवरफ्लो पर अन्य उत्तरों को देखा है, लेकिन वे सभी समरूपता के बारे में प्रतीत होते हैं।

+0

स्मृति स्वामित्व के बारे में बात करनी चाहिए। चूंकि सी में कोई कचरा कलेक्टर नहीं है, इसलिए यह जानना मुश्किल है कि आवंटित वस्तुओं को कब/मुक्त करना होगा। 'unique_ptr' हालांकि मदद कर सकता है। –

+0

यदि यह सार्वजनिक रूप से उपलब्ध है, तो बातचीत को लिंक करें।चाहे वह है या नहीं, कहें कि स्लाइड # या प्रस्तुति में किस समय। –

+0

@ राउन: यह विषय-वस्तु नहीं है, यह डॉ। सटर किसी भी व्यक्ति को बिना किसी जाकर और पूरी बातचीत को देखने और देखने के जवाब देने के लिए कह रहा था। –

उत्तर

5

क्या हर्ब सटर परिपत्र संदर्भ के बारे में बात कर रहा है। उन्होंने कहा कि एक बहुस्तरीय प्रणाली है, जहां संसाधनों कोड के लिए नीचे पारित नहीं कर रहे हैं कि "तक पहुंचता" को बढ़ावा देता है

लेयर 1 - परत 2 (और नीचे) से संसाधनों और वस्तुओं

परत 2 का मालिक - नहीं कर सकते है परत 1 ऑब्जेक्ट्स के मजबूत संदर्भ

यह सुनिश्चित करता है कि निर्भरता के ग्राफ को मंडल नहीं मिलते हैं। तो यदि परत 1 सभी परत 2 ऑब्जेक्ट्स को मुक्त करता है तो सभी संसाधन नष्ट हो जाते हैं। यह महत्वपूर्ण क्यों है यह काफी आसान है: सी ++ एसडीडी लाइब्रेरी से संसाधन गिनती सर्कुलर संदर्भों (कोई रेफ-गिनती कर सकते हैं) से निपट नहीं सकती है, अगर ओबीजे के पास ओबीजे बी का मजबूत संदर्भ है और ओबीजे बी का एक मजबूत संदर्भ है एक obj करने के लिए, तो वे कभी मुक्त नहीं किया जाएगा।

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

यह यह नहीं कह रहा है कि आपको इसे कभी नहीं करना चाहिए, लेकिन यदि आप नियमों के एक समूह का पालन करते हैं तो आप सिस्टम प्रति शेष इनपुट को जानने के बिना कोड प्रति-परत या प्रति फ़ाइल भी सत्यापित कर सकते हैं। अन्यथा आपको कार्य करने के लिए सभी संभावित पथ (ऑन_ड्रा) लेना होगा, यह देखने के लिए कि सर्कुलर डिप्टी का परिणाम क्या हो सकता है - और अगर किसी भी कोड में कुछ भी बदलता है तो संभवतः स्पर्श किया जाता है, तो आपको इसे फिर से करना होगा!

उस संदर्भ में "कॉलबैक नरक" विशेष रूप से समस्याग्रस्त है क्योंकि यह टाइप-सिस्टम को रोकता है (संभावित रूप से केवल निम्न स्तरों से इंटरफेस की अनुमति नहीं देता), और कॉलबैक कुछ भी कर सकता है।

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

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