2014-06-09 7 views
8

का उपयोग कर के रूप में दिखाया गया है here का पता चला है, एक dynamic_cast उपयोग कर सकते हैं किसी हटाए सूचक पता लगाने के लिए:कैसे एक सूचक का विलोपन गतिशील डाली

#include <iostream> 

using namespace std; 

class A 
{ 
public: 
    A() {} 
    virtual ~A() {} 
}; 

class B : public A 
{ 
public: 
    B() {} 
}; 

int main() 
{ 
    B* pB = new B; 

    cout << "dynamic_cast<B*>(pB) "; 
    cout << (dynamic_cast<B*>(pB) ? "worked" : "failed") << endl; 

    cout << "dynamic_cast<B*>((A*)pB) "; 
    cout << (dynamic_cast<B*>((A*)pB) ? "worked" : "failed") << endl; 

    delete pB; 

    cout << "dynamic_cast<B*>(pB) "; 
    cout << (dynamic_cast<B*>(pB) ? "worked" : "failed") << endl; 

    cout << "dynamic_cast<B*>((A*)pB) "; 
    cout << (dynamic_cast<B*>((A*)pB) ? "worked" : "failed") << endl; 

} 

उत्पादन:

dynamic_cast<B*>(pB) worked 
dynamic_cast<B*>((A*)pB) worked 
dynamic_cast<B*>(pB) worked 
dynamic_cast<B*>((A*)pB) failed 

ऐसा नहीं है कि बताते हैं vtable का विलोपन पता चला है।

लेकिन मुझे आश्चर्य है कि यह कैसे संभव है क्योंकि हम मुक्त स्मृति को ओवरराइट नहीं करते हैं?

और क्या यह समाधान पूरी तरह से पोर्टेबल है?

धन्यवाद

+0

मैं अनुमान लगा रहा हूं कि 'गतिशील_कास्ट ' का उपयोग [RTTI] (http://en.wikipedia.org/wiki/Run-time_type_information) का उपयोग करने के लिए किया जा रहा है। –

+0

मुझे संदेह है कि यह मंच निर्भर व्यवहार है। –

+0

विजुअल स्टूडियो 2013 इस कोड के साथ '__non_rtti_object' अपवाद फेंकता है। –

उत्तर

6

पहले, अपरिभाषित व्यवहार में किसी भी रूप परिणामों में एक नष्ट कर दिया वस्तु का उपयोग करने की कोशिश कर रहा: जो कुछ भी आप हो सकता है देखने के परिणाम!

मनाए गए व्यवहार का कारण यह है कि एक वस्तु विनाश के दौरान प्रकार बदलती है: कंक्रीट प्रकार की वस्तु होने से यह पदानुक्रम में सभी प्रकारों के माध्यम से बदल जाती है। प्रत्येक बिंदु पर वर्चुअल फ़ंक्शन बदलते हैं और vtable (या समान) प्रतिस्थापित हो जाता है। dynamic_cast<...>() ऑब्जेक्ट के स्थान पर स्थित बाइट्स में बस इस परिवर्तन का पता लगाता है।

यदि आप यह दिखाना चाहते हैं कि यह तकनीक विश्वसनीय रूप से काम नहीं करती है तो आप हटाए गए मेमोरी की सामग्री को यादृच्छिक बिट पैटर्न या सबसे व्युत्पन्न प्रकार के किसी ऑब्जेक्ट के बिट पैटर्न पर सेट कर सकते हैं: एक यादृच्छिक बिट पैटर्न शायद एक दुर्घटना पैदा करता है और memcpy() शायद दावा करता है कि वस्तु अभी भी जीवन है। बेशक, चूंकि यह अनिर्धारित व्यवहार है, कुछ भी हो सकता है।

पर एक प्रासंगिक अनुभाग इस 3.8 [basic.life] अनुच्छेद 5:

एक वस्तु का जीवन शुरू कर दिया है इससे पहले कि लेकिन भंडारण जो वस्तु पर कब्जा आबंटित किया गया है जाएगा या, के जीवनकाल के बाद के बाद एक ऑब्जेक्ट समाप्त हो गया है और भंडारण से पहले जिस वस्तु पर कब्जा किया गया है उसका पुन: उपयोग या रिलीज़ किया गया है, कोई भी सूचक जो भंडारण स्थान को संदर्भित करता है जहां ऑब्जेक्ट होगा या स्थित था, लेकिन केवल सीमित तरीकों से उपयोग किया जा सकता है। निर्माण या विनाश के तहत किसी वस्तु के लिए, 12.7 देखें। अन्यथा, इस तरह का सूचक आवंटित भंडारण (3.7.4.2) को संदर्भित करता है, और पॉइंटर का उपयोग करता है जैसे कि सूचक void*, टाइप-अच्छी तरह से परिभाषित किया गया है। इस तरह के सूचक के माध्यम से संकेतक की अनुमति है, लेकिन परिणामी अंतराल का उपयोग सीमित तरीके से किया जा सकता है, जैसा कि नीचे वर्णित है। कार्यक्रम व्यवहार अपरिभाषित गया है:

  • ...
  • सूचक एक dynamic_cast (5.2.7) के संकार्य के रूप में प्रयोग किया जाता है। ...

अजीब तरह, dynamic_cast पर अंतिम बुलेट पर उदाहरण dynamic_cast उपयोग नहीं करता।

बेशक, ऑब्जेक्ट भी संभवतः जारी किया जाता है जिस स्थिति में उपर्युक्त गारंटी भी लागू नहीं होती है।

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