2017-02-08 16 views
9

निम्नलिखित कोड पर विचार करें: के रूप में आधुनिक compilers बढ़ीक्यों int int; एक = std :: अधिकतम (एक, एक्स) उत्सर्जन नहीं "अप्रारंभीकृत" चेतावनी

#include <vector> 
#include <algorithm> 
#include <iostream> 

int main() { 
    std::vector<int> v{{1, 2, 3}}; 
    int a; 

    std::cout << a << std::endl; // 1 

    for (const int x : v) { 
     a = std::max(a, x);   // 2 
    } 

    std::cout << a << std::endl; 

    return 0; 
} 

और अब गूंगा प्रोग्रामर गलतियों पर एक सतर्क नजर रखना, वे ट्रैक प्रारंभिक चर हालांकि यह सी ++ कोड उन्हें भ्रमित करता है।

     (1)  (2) 
g++ 5.3.1 
clang++ 3.7    ✔ 
Solaris Studio 12.5  ✔ 

आप देख सकते हैं, बजना और solstudio, केवल मामले (1) का पता लगाने और मामले (2) को अनदेखा कर सकते हैं, जबकि जी ++ दोनों अनदेखी कर रहा है: अब तक, मैं निम्नलिखित परिणाम प्राप्त। मामले में (2) में इसका पता लगाने के लिए कोई जटिलता है? इस पर g ++ इतना बुरा क्यों है?

संकलक विकल्प मैं प्रयोग किया है:

$ g++-5 -std=c++11 -Wall -Wpedantic -pedantic -Wextra \ 
     -Wuninitialized -Wmaybe-uninitialized aisa.cpp 
$ clang++ -std=c++11 -Wall -Wpedantic -pedantic -Wextra -Wuninitialized aisa.cpp 
$ CC -std=c++11 -xprevise aisa.cpp 
+0

दोनों जीसीसी और क्लैंग के बग ट्रैकर्स पर एक फीचर अनुरोध दर्ज करने पर विचार करें - इस तरह की छोटी स्थितियों को शायद अतिरिक्त तर्क –

+2

के साथ पता लगाया जा सकता है यदि आप पहला उदाहरण हटाते हैं तो क्या होता है? क्या क्लैंग या सोलारिस स्टूडियो तब प्रारंभिक चर के बारे में चेतावनी देता है? –

+0

यदि आप अनुकूलन स्तर को क्रैंक करते हैं तो आपको बेहतर चेतावनियां भी मिल सकती हैं। –

उत्तर

3

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

#include <vector> 
#include <algorithm> 
#include <iostream> 

int main() { 
    std::vector<int> v{{1, 2, 3}}; 
    int a; 

    for (const int x : v) { 
     a = std::max(a, x);   // 2 
    } 

    std::cout << a << std::endl; 

    return 0; 

} 

अब हम दो असंबंधित संकलक quirks देखें: बजना-Wall और -Wextra में -Wconditional-uninitialized शामिल नहीं है। यदि आप इसे सक्षम करते हैं, तो आप std::cout पर एक चेतावनी प्राप्त करें क्योंकि यह संभावित रूप से एक अनियमित चर मुद्रित करता है।

जीसीसी दूसरी ओर ऑप्टिमाइज़र सक्षम होने पर केवल अनियमित चर ट्रैक करता है, संभवतः डीबग बिल्डों के संकलन को तेज करने के लिए। -O2 -Wall के साथ, जीसीसी 6 दोनों मामलों में एक चेतावनी फेंकता है, हालांकि दूसरे मामले में स्थान के रूप में सटीक रूप से स्थान को इंगित किए बिना। (gcc < = 5.3 आपके द्वारा देखे गए दूसरे मामले के बारे में चेतावनी नहीं देता है, इसलिए ऐसा लगता है कि हाल ही में लागू किया गया था।)

तो टीएल; डीआर: आपने अपने कंपाइलर्स को सही नहीं बुलाया।

+0

"पहला अपराध" जिसका अर्थ है एक विशिष्ट चेतावनी की पहली घटना, है ना? सामान्य रूप से एक चेतावनी नहीं है? –

+0

@QPaysTaxes हां। अगर आप इसे और अधिक स्पष्ट रूप से बता सकते हैं तो संपादित करने के लिए स्वतंत्र महसूस करें। –

+0

हाँ, मैंने जी ++ का उपयोग किया है 5. आपके उत्तर के लिए धन्यवाद! – myaut

12

std::max, const & द्वारा अपने तर्क लेता है, जबकि int रों के लिए स्ट्रीमिंग ऑपरेटर << मूल्य द्वारा int लेता है। संदर्भ द्वारा एक अनियमित वस्तु को पास करना कानूनी है: उदाहरण के लिए, यदि फ़ंक्शन बस अपना पता लेता है, तो सब ठीक है। इसलिए, a से std::max पास करने पर चेतावनी आसानी से झूठी सकारात्मक हो सकती है।

+1

यह वास्तव में समझ में नहीं आता है कि यह किसी संदर्भ से संबंधित है या नहीं। लेकिन यह एक कॉन्स संदर्भ है। मुझे लगता है कि यह एक ऐसी स्थिति होगी जिसमें संकलक वास्तव में चेतावनी दे सकता है, क्योंकि कोई भी तरीका नहीं है कि आप किसी कॉन्स्ट संदर्भ द्वारा पारित ऑब्जेक्ट को प्रारंभ कर सकें। –

+1

@MarTijn क्या होगा यदि फ़ंक्शन का एकमात्र उद्देश्य ऑब्जेक्ट में 'const *' लेना था और इसे मानचित्र कुंजी के रूप में उपयोग करना था? आप इसे 'कॉन्स' से कर सकते हैं, और आप इसे एक अनियमित वस्तु से भी कर सकते हैं। – Angew

+0

@MarTijn: यदि फ़ंक्शन ऑब्जेक्ट का पता सहेजता है, तो कुछ बाद में चर को प्रारंभ कर सकता है।(या फ़ंक्शन अकेले पते का उपयोग किसी प्रकार के अद्वितीय टैग के रूप में कर सकता है)। –

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