2015-07-09 6 views
130

निम्नलिखित कोड डिबग मोड और रिलीज़ मोड के तहत अलग-अलग परिणाम उत्पन्न करता है (विजुअल स्टूडियो 2008 का उपयोग) :रिलीज मोड में, कोड व्यवहार के रूप में नहीं की उम्मीद है

i: 0, result = 0 
i: 1, result = 16 
(...) 
i:14, result = 224 
i:15, result = 240 
i:16, result = 255 

रिलीज़ मोड, जहां मैं के उत्पादन: 15 परिणाम सही नहीं है:

i: 0, result = 0 
i: 1, result = 16 
(...) 
i:14, result = 224 
i:15, result = 255 
i:16, result = 255 

रिलीज मोड के तहत विजुअल स्टूडियो में "ऑप्टिमाइज़ेशन -> ऑप्टिमाइज़ नहीं करना" चुनकर, आउटपुट परिणाम सही होगा। हालांकि मैं जानना चाहता हूं कि ऑप्टिमाइज़ेशन प्रक्रिया गलत आउटपुट क्यों कर सकती है।


अद्यतन:

मोहित JainBy ने सुझाव दिया है, प्रिंट द्वारा:

printf("i:%2d, result = %3d, i*16=%d\n", i, result, i*16) ; 

रिलीज़ मोड उत्पादन सही है:

i: 0, result = 0, i*16=0 
i: 1, result = 16, i*16=16 
(...) 
i:14, result = 224, i*16=224 
i:15, result = 240, i*16=240 
i:16, result = 255, i*16=256 
+15

यह एक कंपाइलर बग (और उस पर काफी महत्वपूर्ण) जैसा दिखता है। – WhozCraig

+1

@WhozCraig बस पोस्ट में 'i * 16' के आउटपुट को अपडेट करता है, और परिणाम सही है। –

+4

@juanchopanza: एमएस और बगफिक्स से वीएस के साथ अपने अनुभव से वे उनके बारे में सूचित होने के बाद ऐसी बग ठीक करते हैं, लेकिन उन फिक्सेस को वीएस के पुराने संस्करणों पर लागू न करें, इसलिए यदि किसी किसी कारण से किसी पुराने व्यक्ति का उपयोग करने के लिए मजबूर होना पड़ता है वीएस का संस्करण, तब तक कोई भी ऐसी बग्स से फंस जाता है जब तक कोई एक नए संस्करण में अपग्रेड नहीं कर सकता। – Kaiserludi

उत्तर

114

यह दिलचस्प है, कम से कम एक ऐतिहासिक परिप्रेक्ष्य से। मैं वीसी 2008 (15.00.30729.01) और वीसी 2010 (16.00.40219.01) (32-बिट x86 या 64-बिट x64 को लक्षित करना) के साथ समस्या का पुन: उत्पन्न कर सकता हूं। समस्या किसी भी कंपाइलर के साथ नहीं होती है जिसे मैंने वीसी 2012 (17.00.61030) से शुरू करने का प्रयास किया है।

आदेश मैं संकलित करने के लिए प्रयोग किया है: cl /Ox vc15-bug.cpp /FAsc

के बाद कुलपति 2008 (और 2010) के बजाय पुरानी है और ठीक अब कई वर्षों के लिए किया गया है, मुझे नहीं लगता कि आप को छोड़कर Microsoft से किसी भी कार्रवाई की उम्मीद कर सकते हैं एक नए कंपाइलर का उपयोग करने के लिए (हालांकि शायद कोई कामकाज का सुझाव दे सकता है)।

समस्या यह है कि यह निर्धारित करने के लिए परीक्षण 255 को i * 16 अभिव्यक्ति के वास्तविक परिणाम की बजाय लूप गणना के आधार पर किया जाना चाहिए या नहीं। और संकलक को गिनती गलत हो जाती है जब इसे 255 पर मूल्य को मजबूर करना शुरू करना चाहिए। क्यों ऐसा होता है मुझे पता नहीं है - यह सिर्फ प्रभाव है कि मैं देख रहा हूँ है:

; 6 : for(int i = 0; i < 17; i++) 

    00001 33 f6  xor  esi, esi 
[email protected]: 
    00003 8b c6  mov  eax, esi 
    00005 c1 e0 04  shl  eax, 4 

; 7 : { 
; 8 :  int result = i * 16; 
; 9 : 
; 10 :  if(result > 255) 

    // the value `esi` is compared with in the following line should be 15! 
    00008 83 fe 0e  cmp  esi, 14   ; 0000000eH 
    0000b 7e 05  jle  SHORT [email protected] 

; 11 :  { 
; 12 :   result = 255; 

    0000d b8 ff 00 00 00 mov  eax, 255  ; 000000ffH 
[email protected]: 

; 13 :  } 

अद्यतन: - कार्यक्रम दुर्घटनाओं संकलन कुलपति के सभी संस्करणों मैं कुलपति 2008 की तुलना में पहले स्थापित किया है एक ही बग है VC6 को छोड़कर, VC6 संकलक:

vc15-bug.cpp(10) : fatal error C1001: INTERNAL COMPILER ERROR 

तो यह एक बग है कि एक के रूप में MSVC में चली या 10 से अधिक वर्षों के लिए एक और है!

+0

के साथ ठीक काम करता है यदि x86 असेंबली समय की मेरी याददाश्त ईएक्स की तुलना में ईएसई की तुलना के लिए सही है, तो ईएक्स कॉम्प ईएक्स है, 255 एक पाइपलाइन स्टॉल का कारण बनता है क्योंकि ईएक्स अभी लिखा गया है। –

+3

मेरा अनुमान (परिवर्तन): परिणाम> 255, परिणाम/16> 255/16, i> 15, i <= 14 – teki

+0

बहुत रोचक! इसके अलावा यदि आप 'परिणाम> 255' से' परिणाम> = 255' से तुलना बदलते हैं तो यह सही तरीके से व्यवहार करता है। वीएस -2010 में जो 'cmp esi, 14' से' cmp esi, 16' (और 'jle' से' jl') बदलता है। – opello

16

आपके द्वारा बताए गए तथ्यों मानते हुए हैं सही, यह एक कंपाइलर बग होगा। कंपाइलर का नवीनतम संस्करण देखें। अगर बग अभी भी मौजूद है, तो एक बग रिपोर्ट सबमिट करें।

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