7

मैं वीसी 9 के साथ बनाए गए एप्लिकेशन पर काम कर रहा हूं और मैंने एक चेतावनी पर मारा है जिसे मैं पूरी तरह से समझ नहीं पा रहा हूं: क्यों बंद होने पर "पहुंचने योग्य कोड" चेतावनी है निर्माता?कन्स्ट्रक्टर के बंद ब्रेस पर पहुंचने योग्य कोड

न्यूनतम testcase समस्या को पुनः के लिए है:

__declspec(noreturn) void foo() { 
    // Do something, then terminate the program 
} 
struct A { 
    A() { 
    foo(); 
    } // d:\foo.cpp(7) : warning C4702: unreachable code 
}; 
int main() { 
    A a; 
} 

यह चेतावनी को गति प्रदान करने/W4 साथ संकलित किया जाना चाहिए। वैकल्पिक रूप से, आप इस चेतावनी का पता लगाने पर त्रुटि को बल देने के लिए/we4702 के साथ संकलित कर सकते हैं।

d:\>cl /c /W4 foo.cpp 
Microsoft (R) C/C++ Optimizing Compiler Version 15.00.21022.08 for x64 
Copyright (C) Microsoft Corporation. All rights reserved. 

foo.cpp 
d:\foo.cpp(7) : warning C4702: unreachable code 

कोई व्याख्या कर सकते हैं क्या, ठीक है, यहाँ तक पहुँचा? मेरा सबसे अच्छा सिद्धांत यह है कि यह विनाशक है, लेकिन मुझे एक निश्चित उत्तर चाहिए।

अगर मैं यह कोड चेतावनी-साफ करना चाहता हूं, तो मैं इसे कैसे प्राप्त कर सकता हूं? सबसे अच्छा मैं साथ आ सकता हूं इसे संकलित-समय त्रुटि में परिवर्तित कर रहा है।

struct A { 
private: 
    A(); // No, you can't construct this! 
}; 
int main() { 
    A a; 
} 

संपादित करें: स्पष्टीकरण के लिए, एक noreturn समारोह के साथ कार्यक्रम समाप्त सामान्य रूप से एक नहीं पहुंचा जा सकता कोड समापन ब्रेस enclosing कि समारोह फोन पर चेतावनी का कारण नहीं है। में

__declspec(noreturn) void foo() { 
    // Do something, then terminate the program 
} 
struct A { 
    A() { 
    } 
    ~A() { 
    foo(); 
    } 
}; 
int main() { 
    A a; 
} 

परिणाम:

d:\>cl /c /W4 foo3.cpp 
Microsoft (R) C/C++ Optimizing Compiler Version 15.00.21022.08 for x64 
Copyright (C) Microsoft Corporation. All rights reserved. 

foo3.cpp 
+7

क्योंकि आप 'foo()' में प्रोग्राम को समाप्त करते हैं? – juanchopanza

+0

कुछ 'निजी' बनाना और इसे कार्यान्वित नहीं करना सामान्य तरीका है, ** सी ++ 11 ** को प्राप्त करने के लिए '= delete' है। –

+1

'foo() '' __declspec (noreturn) होना चाहिए'? – ixe013

उत्तर

3

गोर्पिक सही रास्ते पर है। मैंने दो समान टेस्ट केस बनाए हैं, उन्हें संकलित किया है, और उन्हें अलग किया है और मुझे लगता है कि मैं अंतर्निहित कारण को समझने आया हूं: कन्स्ट्रक्टर हमेशा एक रिटर्न स्टेटमेंट उत्पन्न करता है और यह रिटर्न स्टेटमेंट नॉरटर्न फ़ंक्शन के कारण पहुंच योग्य नहीं है।

noreturn_constructor.cpp

__declspec(noreturn) void foo() { 
    // Do something, then terminate the program 
} 
struct A { 
    A() { 
    foo(); 
    } 
    ~A() { 
    } 
}; 
int main() { 
    A a; 
} 

noreturn_destructor।सीपीपी

__declspec(noreturn) void foo() { 
    // Do something, then terminate the program 
} 
struct A { 
    A() { 
    } 
    ~A() { 
    foo(); 
    } 
}; 
int main() { 
    A a; 
} 

diff -u * .disasm

--- noreturn_constructor.disasm 2012-05-30 11:15:02.000000000 -0400 
+++ noreturn_destructor.disasm 2012-05-30 11:15:08.000000000 -0400 
@@ -2,7 +2,7 @@ 
Copyright (C) Microsoft Corporation. All rights reserved. 


-Dump of file noreturn_constructor.obj 
+Dump of file noreturn_destructor.obj 

File Type: COFF OBJECT 

@@ -35,15 +35,15 @@ 

[email protected]@[email protected] (public: __cdecl A::A(void)): 
    0000000000000000: 48 89 4C 24 08  mov   qword ptr [rsp+8],rcx 
- 0000000000000005: 48 83 EC 28  sub   rsp,28h 
- 0000000000000009: E8 00 00 00 00  call  [email protected]@YAXXZ 
- 000000000000000E: 48 8B 44 24 30  mov   rax,qword ptr [rsp+30h] 
- 0000000000000013: 48 83 C4 28  add   rsp,28h 
- 0000000000000017: C3     ret 
+ 0000000000000005: 48 8B 44 24 08  mov   rax,qword ptr [rsp+8] 
+ 000000000000000A: C3     ret 

[email protected]@[email protected] (public: __cdecl A::~A(void)): 
    0000000000000000: 48 89 4C 24 08  mov   qword ptr [rsp+8],rcx 
- 0000000000000005: C3     ret 
+ 0000000000000005: 48 83 EC 28  sub   rsp,28h 
+ 0000000000000009: E8 00 00 00 00  call  [email protected]@YAXXZ 
+ 000000000000000E: 48 83 C4 28  add   rsp,28h 
+ 0000000000000012: C3     ret 

    Summary 

पहुँच योग्य नहीं कोड इस अंतर्निहित वापसी बयान है, जो निर्माता में उत्पन्न होता है लेकिन नहीं नाशक है:

- 000000000000000E: 48 8B 44 24 30  mov   rax,qword ptr [rsp+30h] 
+ 0000000000000005: 48 8B 44 24 08  mov   rax,qword ptr [rsp+8] 
1

foo पर declspec (noreturn) इस चेतावनी का निर्माण कर रहा है। आप संकलक को बता रहे हैं कि यह फ़ंक्शन वापस नहीं आता है। तो संकलक एक चेतावनी उत्सर्जित कर रहा है कि आपका कन्स्ट्रक्टर कभी पूरा नहीं होगा।

+0

मैं अपने मूल प्रश्न में बहुत अस्पष्ट हो सकता हूं, लेकिन मुझे नहीं लगता कि यह एक उत्तर में जो कुछ मैं ढूंढ रहा हूं उसका सार कैप्चर करता है: एक कन्स्ट्रक्टर एक पहुंचने योग्य कोड चेतावनी में परिणाम समाप्त करने से पहले एक न्यूरटर्न फ़ंक्शन क्यों कॉल करता है किसी अन्य फ़ंक्शन को समाप्त करने से पहले उसी नोरटर्न फ़ंक्शन को कॉल करना ** नहीं ** परिणामस्वरूप पहुंचने योग्य कोड चेतावनी है? – mrkj

1

http://msdn.microsoft.com/en-us/library/k6ktzx3s(v=vs.80).aspx

देख "यह __declspec विशेषता संकलक है कि एक समारोह वापस नहीं करता है बताता है। परिणामस्वरूप, संकलक जानता है कि कोड एक __declspec के लिए एक कॉल निम्नलिखित (noreturn) समारोह नहीं पहुंचा जा सकता है।"

समापन ब्रेस कोड उत्पन्न कर सकता है (जैसे विनाशकों को बुलावा), जो तक नहीं पहुंचाया जाएगा।

+1

क्या आप इस मामले में जेनरेट कोड पहुंचने योग्य नहीं हैं, इसके बारे में अधिक विशिष्ट हो सकते हैं? सवाल था ** क्या, ठीक है, पहुंच योग्य नहीं है ** (नहीं "__declspec (noreturn)' मतलब क्या है ")। इस मामले में विनाशक के लिए कोई कोड उत्पन्न नहीं होना चाहिए; विनाशक क्या कर रहा होगा? यह विनाशक के कोड को कन्स्ट्रक्टर के बंद ब्रेस में क्यों विशेषता देगा? – mrkj

+0

आपका सही है, स्पष्टीकरण बहुत सरल है। कोड के डिस्सेप्लर को देखते हुए, समापन ब्रेस निर्माता के लिए विनाशक के लिए समान कोड उत्पन्न करता है। तो मेरी समझ के लिए चेतावनी दोनों मामलों में उत्पन्न होनी चाहिए (जो मैं उम्मीद नहीं करता) या किसी में भी नहीं। बीटीडब्ल्यू, एक सामान्य (या वर्चुअल) विधि भी कोई चेतावनी उत्पन्न नहीं करती है। – Stefan

2

A::A() के अंत में कोई विनाशक नहीं कहा जाता है, इसलिए यह समस्या नहीं है। क्या पहुंचा जा सकता है वस्तु का वास्तविक निर्माण, जो कि कन्स्ट्रक्टर के निष्पादन के समाप्त होने के बाद होता है। चूंकि यह कभी खत्म नहीं हो सकता है, इसलिए संकलक-जेनरेट कोड पहुंच योग्य नहीं है।

+1

मुझे लगता है कि यह एक दिलचस्प सिद्धांत है। कन्स्ट्रक्टर के उपयोगकर्ता द्वारा निर्दिष्ट निकाय के अलावा, "ऑब्जेक्ट का वास्तविक निर्माण" बनाने के लिए कौन सा कोड उत्पन्न होता है? – mrkj

+1

उपयोगकर्ता परिभाषित कन्स्ट्रक्टर के बाद * कौन सा कोड चलाया जाता है? मेरा मतलब है कि स्पष्ट रूप से मेमोरी आवंटित करना, * उपयोगकर्ता कन्स्ट्रक्टर को कॉल करने से पहले * किया जाना है, तो और क्या है? – Voo

+0

@mrkj: मुझे लगता है कि आपने इस मुद्दे की जांच की है, इसलिए मेरे पास कुछ भी जोड़ने की ज़रूरत नहीं है। वैसे भी विवरण और प्रयोगात्मक पुष्टि के लिए अपने उत्तर में +1 करें। – Gorpik

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