2013-05-09 4 views
5

से वापसी पर विचार करें एक छोटी इकाई परीक्षण का मामलाभिन्नता और संदर्भ

struct A 
{ 
    virtual void func(){} 
    A& foo() 
    { 
    A *obj = reinterpret_cast<A*>(0xdeadbeef); 
    return *obj; //1 
    } 
}; 

int main() 
{ 
    A obj = obj.foo(); 
} 

लाइन 1 पर है यह कार्यान्वयन परिभाषित/अनिर्दिष्ट सम्मान नहीं होगा कि के रूप में हम संदर्भ द्वारा लौट रहे हैं और इस कार्यक्रम के लिए एक है, तो दुर्घटना नहीं होता ऑब्जेक्ट की ओर इशारा करने के लिए स्पष्ट पहुंच नहीं बनाई गई है?

मुझे अपने सहयोगियों में से एक के साथ तर्क था जिसमें उन्होंने उल्लेख किया था कि अधिकांश मामलों में कंपाइलर obj की अव्यवस्था को अनुकूलित करेगा क्योंकि हम इसे संदर्भ द्वारा वापस कर रहे हैं और यह कोड क्रैश नहीं होगा?

धन्यवाद

+0

मेरी समझ यह है कि: कंपाइलर 1 के लिए बाध्य नहीं है) रन कोड जिसके परिणामस्वरूप कुछ भी नहीं हो रहा है 2) रन कोड जो एक अपरिभाषित व्यवहार उत्पन्न करता है: http://blog.llvm.org/2011/05/what-every- सी-प्रोग्रामर-चाहिए-know_14.html – Patashu

+0

यहां तक ​​कि मेरा मानना ​​है कि व्यवहार अपरिभाषित है और हमें इस मामले में अंतर्निहित कार्यान्वयन पर भरोसा नहीं करना चाहिए। –

+2

यह अनिर्धारित व्यवहार है और आपको कभी भी अपरिभाषित व्यवहार पर भरोसा नहीं करना चाहिए जो आपको लगता है कि यह क्या करेगा, हां। लेकिन यह आवश्यक रूप से क्रैश नहीं होगा, अगर संकलक निर्णय लेता है कि यह मृत कोड है या अनिर्धारित है और अकादमिक परिप्रेक्ष्य से बोलने के लिए कोड तैयार करने योग्य नहीं है। – Patashu

उत्तर

4

मैं एमएस VC8.0 में कोड एकत्रित न, और अधिक दिलचस्प चीजों को खोजने:

006D48D6 mov   dword ptr [ebp-8],ecx 
    A *obj = reinterpret_cast<A*>(0xdeadbeef); 
006D48D9 mov   dword ptr [obj],0DEADBEEFh 
     return *obj; //1 
006D48E0 mov   eax,dword ptr [obj] //2 
    } 
006D48E3 mov   esp,ebp 
006D48E5 pop   ebp 
006D48E6 ret  

// 2 से पता चलता है कि सिर्फ वापसी मान के रूप में EAX रजिस्टर करने के लिए obj का पता डाल ।

006D39FC lea   ecx,[ebp-190h] 
006D3A02 call  A::foo (6A8C12h) 
006D3A07 push  eax //3 
006D3A08 lea   ecx,[ebp-190h] 
006D3A0E call  A::A (6B89BEh) 

ईएक्स 0xdeadbeef है, और अस्थायी स्थानीय चर के रूप में ढेर करने के लिए धक्का। हम कॉपी कन्स्ट्रक्टर (जो तुच्छ है) कहते हैं। ये सभी कार्य केवल पते को पारित कर रहे हैं (जो अवैध है लेकिन कार्यक्रम परवाह नहीं है)। क्योंकि एक स्ट्रक्चर में कोई सदस्य नहीं है जो विशिष्ट ऑब्जेक्ट से जुड़ा हुआ है, और प्रोग्राम विशिष्ट ऑब्जेक्ट को डिफरेंस द्वारा खोजने की कोशिश नहीं करेगा अगर यह ' टी जरूरत नहीं है। तो इस बम को निकाल दिया नहीं गया है। क्योंकि ऑपरेटर = भी संदर्भ जो वास्तव में address.If पारित से गुजरती है

 A *obj = reinterpret_cast<A*>(0xdeadbeef); 
     A tmp ; 
     temp = *obj; 

यहां तक ​​कि यह ठीक है आप एक सदस्य चर जोड़ने के लिए, यह असफल है क्योंकि यह खोजने के लिए और सदस्य नकल करने की कोशिश करेंगे होगा।

+2

+1 खोदने के लिए +1, भले ही यह सवाल का जवाब न दे। – qdii

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