2016-08-31 10 views
21

कल समारोह कॉल गुणा दूर के अनुकूलन मैं अपने सी # कोड में यह अजीब व्यवहार का पता चला:रोसलिन संकलक के साथ शून्य

Stack<long> s = new Stack<long>(); 

s.Push(1);   // stack contains [1] 
s.Push(2);   // stack contains [1|2] 
s.Push(3);   // stack contains [1|2|3] 

s.Push(s.Pop() * 0); // stack should contain [1|2|0] 

Console.WriteLine(string.Join("|", s.Reverse())); 

मैं ग्रहण कार्यक्रम 1|2|0 मुद्रित होगा, लेकिन वास्तव में यह 1|2|3|0 छपी।

(ILSpy के माध्यम से) उत्पन्न आईएल कोड को देखते हुए आप देख सकते हैं कि s.Pop() * 0 बस 0 के लिए अनुकूलित है:

// ... 
IL_0022: ldloc.0 
IL_0023: ldc.i4.0 
IL_0024: conv.i8 
IL_0025: callvirt instance void class [System]System.Collections.Generic.Stack`1<int64>::Push(!0) 
// ... 

ILSpy decompilation:

Stack<long> s = new Stack<long>(); 
s.Push(1L); 
s.Push(2L); 
s.Push(3L); 
s.Push(0L); // <- the offending line 
Console.WriteLine(string.Join<long>("|", s.Reverse<long>())); 

सबसे पहले मैं शुरू में के तहत इस परीक्षण किया विजुअल स्टूडियो 2015 अपडेट 3 के साथ विंडोज 7 दोनों रिलीज मोड (/optimize) और डीबग मोड और विभिन्न लक्ष्य ढांचे (4.0, 4.5, 4.6 और 4.6.1) के साथ। सभी 8 मामलों में परिणाम वही था (1|2|3|0)।

फिर मैंने इसे विंडोज 7 के तहत विजुअल स्टूडियो 2013 अपडेट 5 (फिर से रिलीज/डीबग मोड और लक्ष्य ढांचे के सभी संयोजनों के साथ) के साथ परीक्षण किया। मेरे आश्चर्य के लिए कथन यहां है ऑप्टिमाइज़ किया गया और अनुमानित परिणाम 1|2|0 उत्पन्न करता है।

तो मैं निष्कर्ष निकाल सकता हूं कि यह व्यवहार न तो /optimize पर निर्भर करता है और न ही लक्षित फ्रेमवर्क ध्वज बल्कि उपयोग किए गए कंपाइलर संस्करण पर निर्भर करता है।

ब्याज से मैंने सी ++ में एक समान कोड लिखा और इसे वर्तमान जीसीसी संस्करण के साथ संकलित किया। यहां शून्य के साथ गुणा किया गया फ़ंक्शन कॉल ऑप्टिमाइज़ नहीं किया गया है और फ़ंक्शन ठीक से निष्पादित किया गया है।

मुझे लगता है कि ऐसा अनुकूलन केवल तभी मान्य होगा जब stack.Pop() शुद्ध कार्य था (जो यह निश्चित रूप से नहीं है)। लेकिन मुझे यह बग कॉल करने में संकोच नहीं है, मुझे लगता है कि यह सिर्फ एक विशेषता है जो मुझे अज्ञात है?

क्या यह "फीचर" कहीं भी दस्तावेज है और क्या इस अनुकूलन को अक्षम करने का एक आसान तरीका है?

+4

नीरस पर बग/ठीक की प्रगति को ट्रैक कर सकते हैं, हाँ, मैं VS2015 अद्यतन 2. साथ repro कर सकते हैं रोसलिन एक प्रमुख बग जनरेटर किया गया है। इसकी रिपोर्ट करने के लिए [नया अंक बटन] (https://github.com/dotnet/roslyn/issues) पर क्लिक करें। पॉप रिटर्न वैल्यू को स्टोर करने के लिए एक चर का उपयोग करके लिंप करें, इसे जिटर ऑप्टिमाइज़र द्वारा फिर से हटा दिया जाएगा। –

+0

यह सबसे अधिक संभावना है कि इसे ऑफ़ साइट संसाधन के लिंक के बिना उत्तर नहीं दिया जा सकता है (जो इसे विषय से दूर करता है)। यह एक शानदार बग रिपोर्ट है जिसे यहां सबमिट किया जाना चाहिए https://github.com/dotnet/roslyn/issues बेशक, टीम का कोई भी जवाब दे सकता है ... शायद जेरेड पार्सन्स? – Will

+0

@ हंसपैसेंट: मुझे लगता है कि यह एक बग नहीं है लेकिन एक सुविधा है :)। लेकिन अगर ऐसा है तो मैं एक मुद्दा खोलूंगा और अपने कोड-जेनरेटर को अब अपनी लाइन में Stack.Pop() को स्पष्ट रूप से कॉल करने के लिए बदल दूंगा। – Mikescher

उत्तर

12

हां, यह निश्चित रूप से एक बग है। < expr> * 0,expr> में साइडफ्रेम होने पर 0 में अनुकूलित नहीं किया जाना चाहिए।

इस मुद्दे की रिपोर्ट करने के लिए धन्यवाद !!

आप https://github.com/dotnet/roslyn/issues/13486

+1

इस तरह के मुद्दों के साथ आप इतने उत्तरदायी होने के लिए लोगों के लिए धन्यवाद। – Will

+1

फ़िक्स को https://github.com/dotnet/roslyn/pull/13501 – VSadov

+0

वाह में विलय कर दिया गया है, यह कमाल है। एमएस विकास हाल ही में कैसे जा रहा है इस बारे में वास्तव में खुश हूं। क्या आप लोग फोन समूह में जा सकते हैं और उन्हें पागल में चौकोर कर सकते हैं? मुझे डब्ल्यूपी मंच के लिए डर है। गंभीरता से, मैं इसके लिए डरता हूं। – Will

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