2011-02-01 4 views
6

उदाहरण मैंने देखा है COM IUnknown::Release() समारोह कार्यान्वयन से ऐसा ही कुछ है:COM IU अज्ञात :: रिलीज कार्य का यह कार्यान्वयन क्यों करता है?

ULONG Release() 
{ 
    InterlockedDecrement(&m_count); 
    if(m_count == 0) { 
     delete this; 
    } 
    return m_count; 
} 

तो, अगर m_count 0 है, इसलिए हम हटा रहे हैं, "इस" वस्तु, और रेफरी गिनती लौटने। जो मुझे समझ में नहीं आता है वह क्यों काम करता है?!?

  1. वस्तु को हटाया जा रहा कॉल स्टैक को बर्बाद नहीं होगा या यह ठीक है क्योंकि यह धागा द्वारा आयोजित किया जा रहा है, इसलिए यह वस्तु के साथ कोई संबंध नहीं है है ???

  2. यदि ऑब्जेक्ट हटा दिया गया है, तो यह कैसे संभव है कि हम m_count वापस कर सकें, इसे हटा दिया जाना चाहिए था। मैं खुद को आश्वस्त कर सकता था कि यह ठीक है अगर हटाए जाने के बाद कोड हार्ड-कोड 0 लौटाएगा, लेकिन यह सदस्य कैसे वापस आ सकता है?!?

आपकी मदद के लिए बहुत बहुत धन्यवाद! :-)

+1

+1 आप सही हैं - या तो यह छोटी गाड़ी कोड है या यहाँ काम पर कुछ और नीच है। मैं उत्सुक हूं अगर COM के साथ अधिक अनुभव वाला कोई व्यक्ति इसका उत्तर दे सकता है, लेकिन मेरा गॉटशॉट यह है कि यह गलत है। – templatetypedef

उत्तर

15

वह कोड फर्जी है। के बाद कोई भी m_count पर भरोसा नहीं कर सकता है। सही कोड हमेशा इस तरह है:

ULONG Release() 
{ 
    ULONG count = InterlockedDecrement(&m_count); 
    if(count == 0){ delete this; } 
    return count; 
} 
+0

क्या आपका मतलब है "** ** * हटाएं * *? –

+2

नहीं, वह कमी के बाद था। यदि एकाधिक धागे इस तक पहुंच रहे हैं, तो यह संभव है कि एक और धागा भी रिलीज को कॉल करता है, जो सदस्य परिवर्तनीय ऋणात्मक मान का मूल्य बनाता है यदि यह कमी और सशर्त के बीच किया जाता है। –

+6

नहीं, वास्तव में 'कमी' के बाद मेरा मतलब है। 'हटाएं' के बाद 'this' को संदर्भित करने का मुद्दा स्पष्ट है और दोहराने की आवश्यकता नहीं है। लेकिन समेकन का एक और सूक्ष्म मुद्दा है। आपकी कमी से गिनती आ सकती है, कहें, 2. जब तक आप m_count को दोबारा स्पर्श नहीं करते हैं, क्योंकि आपने पहले से ही अपनी गिनती जारी की है, * अन्य * धागे 0 तक पहुंच चुके हैं और ऑब्जेक्ट जारी कर चुके हैं, और स्लॉट को भी फिर से आवंटित किया जा सकता है कुछ और। तो विचलन * हिक संट लियोन * के बाद m_count को स्पर्श न करें। –

1

आप क्या देखते अपरिभाषित व्यवहार है। कॉल स्टैक delete this; और delete this by itself is always safe लेकिन renders this pointer invalid द्वारा बदला नहीं गया है जिसका अर्थ है कि अब आप इसे अस्वीकार नहीं कर सकते हैं।

आपके द्वारा देखी जाने वाली दो संभावित स्पष्टीकरण हैं। या तो कार्य में कार्यान्वयन this सूचकांक को वापस करने पर m_count प्राप्त करने के लिए सूचक नहीं है - यह इसे एक रजिस्टर पर लोड किया गया है और केवल उस मान का उपयोग करता है और इसलिए this को संदर्भित नहीं किया गया है और आप किसी भी समस्या का पालन नहीं करते हैं या delete ऑब्जेक्ट द्वारा कब्जा कर लिया गया स्मृति समाप्त हो गया है, अभी भी प्रक्रिया पता स्थान में मैप किया गया है और तकनीकी रूप से सुलभ बना हुआ है और इसलिए this सफल और m_count सफलतापूर्वक पढ़ा गया है। मुझे लगता है कि उत्तरार्द्ध अधिक संभावना है।

जो भी स्पष्टीकरण अनिश्चित व्यवहार है, आप उस पर भरोसा नहीं कर सकते हैं, user Remus Rusanuin his answer का सुझाव देता है।

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