2016-07-13 22 views
11

यह एक सरल C++ कार्यक्रम है का उपयोग कर valarrays:जीसीसी अनुकूलन वैलेरिएज़ के साथ क्यों काम नहीं करता है?

#include <iostream> 
#include <valarray> 

int main() { 
    using ratios_t = std::valarray<float>; 

    ratios_t a{0.5, 1, 2}; 
    const auto& res (ratios_t::value_type(256)/a); 
    for(const auto& r : ratios_t{res}) 
     std::cout << r << " " << std::endl; 
    return 0; 
} 

अगर मैं संकलन और इस तरह इसे चलाने:

g++ -O0 main.cpp && ./a.out 

आउटपुट के रूप में की उम्मीद है:

512 256 128 

हालांकि, अगर मैं इसे संकलित करता हूं और इसे चलाता हूं:

g++ -O3 main.cpp && ./a.out 

उत्पादन होता है: अगर मैं -O1 अनुकूलन पैरामीटर का उपयोग

0 0 0 

एक ही होता है।

जीसीसी संस्करण (Archlinux में नवीनतम) है:

$ g++ --version 
g++ (GCC) 6.1.1 20160707 

हालांकि, अगर मैं बजना के साथ प्रयास करें, दोनों

clang++ -std=gnu++14 -O0 main.cpp && ./a.out 

और

clang++ -std=gnu++14 -O3 main.cpp && ./a.out 

ही सही परिणाम का उत्पादन:

512 256 128 

बजना संस्करण है:

$ clang++ --version 
clang version 3.8.0 (tags/RELEASE_380/final) 

मैं भी डेबियन, जहां निष्पादन सही परिणाम का उत्पादन पर जीसीसी 4.9.2 के साथ की कोशिश की है।

क्या यह जीसीसी में एक संभावित बग है या क्या मैं कुछ गलत कर रहा हूं? क्या कोई इसे पुन: उत्पन्न कर सकता है?

संपादित करें: मैक ओएस पर जीसीसी 6 के होमब्रू संस्करण पर भी इस मुद्दे को पुन: उत्पन्न करने में कामयाब रहा।

+0

http://melpon.org/wandbox यह 4.9.3 से 5.1 करने के लिए व्यवहार में परिवर्तन दिखाई देता है का उपयोग करना। – NathanOliver

+0

दुर्भाग्यवश, मेरे कोडबेस में मैंने जीसीसी 4.9.3 पर भी इसी तरह की समस्या (लेकिन uint32_t के साथ) को पुन: पेश करने में कामयाब रहा है, हालांकि यह न्यूनतम उदाहरण में डालने पर काम करता है। मैं जांच कर रहा हूं ... – DoDo

उत्तर

6

valarray और auto अच्छी तरह से मिश्रण न करें।

यह एक अस्थायी वस्तु बनाता है, फिर operator/ लागू होता है इसे करने के लिए:

const auto& res (ratios_t::value_type(256)/a); 

libstdC++ ताकि operator/ एक हल्के उद्देश्य यह है कि मूल तर्क को संदर्भित करता है और उन्हें lazily का मूल्यांकन करता है रिटर्न valarray अभिव्यक्ति टेम्प्लेट का उपयोग किया। आप const auto& का उपयोग करते हैं जो अभिव्यक्ति टेम्पलेट को संदर्भ के लिए बाध्य करने का कारण बनता है, लेकिन अभिव्यक्ति टेम्पलेट को अस्थायी के जीवनकाल का विस्तार नहीं करता है, इसलिए जब मूल्यांकन होता है तो अस्थायी गुंजाइश से बाहर हो गया है, और इसकी याददाश्त हो गई है पुन: उपयोग किया।

यह ठीक कार्य करेगा जब आप कार्य करें:

ratios_t res = ratios_t::value_type(256)/a; 
+0

विस्तृत उत्तर के लिए धन्यवाद। मैं इसे स्वीकार करूंगा। मैं बस यह ध्यान रखना चाहूंगा कि भले ही मैं 'ऑटो रेज (ratios_t :: value_type (256)/a) लिखूं, फिर भी, मुझे अभी भी अनुकूलन के साथ एक ही परिणाम मिल गया है। हालांकि, आपका सुझाव काम करता है (यानी 'ऑटो' का उपयोग नहीं कर रहा है)। दोनों clang और msvc मूल कोड सही ढंग से काम किया। – DoDo

+0

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

+0

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57997 एक बहुत ही समान समस्या है। –

3

यह operator/ (const T& val, const std::valarray<T>& rhs) (valarrays से अधिक और सबसे शायद अन्य ऑपरेटरों) आलसी मूल्यांकन का उपयोग करने का लापरवाह कार्यान्वयन का परिणाम है:

#include <iostream> 
#include <valarray> 

int main() { 
    using ratios_t = std::valarray<float>; 

    ratios_t a{0.5, 1, 2}; 
    float x = 256; 
    const auto& res (x/a); 
    // x = 512; // <-- uncommenting this line affects the output 
    for(const auto& r : ratios_t{res}) 
     std::cout << r << " "; 
    return 0; 
} 

"x = 512" बाहर टिप्पणी की लाइन के साथ, उत्पादन

512 256 128 
है

उस पंक्ति और आउटपुट में

1024 512 256 

चूंकि आपके उदाहरण में विभाजन ऑपरेटर का बाएं हाथ की तरफ तर्क अस्थायी है, परिणाम अपरिभाषित है।

अद्यतन

Jonathan Wakely सही ढंग से pointed out के रूप में, आलसी मूल्यांकन आधारित कार्यान्वयन इस उदाहरण में एक समस्या auto के उपयोग के कारण हो जाता है।

+0

आपके उत्तर के लिए धन्यवाद। जोनाथन पहले था इसलिए मैंने उसका जवाब स्वीकार कर लिया, लेकिन आपका भी बहुत जानकारीपूर्ण है। बहुत बुरा एसओ आपको कई उत्तरों को स्वीकार नहीं करने देता है :-)। – DoDo

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