c# शायद विजुअल स्टूडियो 2015 में एक सी # कंपाइलर बग


1 Answers

सबसे पहले, यह महत्वपूर्ण है कि इन मुद्दों का विश्लेषण एक न्यूनतम पुनरुत्पादक बनाने के लिए करें, ताकि हम समस्या को कम कर सकें। मूल कोड में तीन लाल बालियां हैं: readonly , static और Nullable<T> । इस मुद्दे को पुनर्जीवित करने के लिए कोई भी आवश्यक नहीं है। यहां एक न्यूनतम रेपो है:

struct N<T> {}
struct M { public N<M> E; }
class P { static void Main() { var x = default(M); } }

यह वीएस के वर्तमान संस्करण में संकलित है, लेकिन रन करते समय एक प्रकार लोड अपवाद फेंकता है।

  • अपवाद E उपयोग से ट्रिगर नहीं किया गया है। यह प्रकार M तक पहुंचने के किसी भी प्रयास से ट्रिगर किया जाता है। (जैसा कि एक प्रकार के लोड अपवाद के मामले में उम्मीद है।)
  • अपवाद पुन: उत्पन्न करता है कि क्या क्षेत्र स्थैतिक या उदाहरण है, केवल पढ़ने या नहीं; इस क्षेत्र की प्रकृति से कोई लेना देना नहीं है। (हालांकि यह एक क्षेत्र होना चाहिए! अगर यह एक विधि है, तो मुद्दा repro नहीं करता है।)
  • अपवाद में "आमंत्रण" के साथ कुछ भी नहीं करना है; न्यूनतम repro में कुछ भी "आह्वान" किया जा रहा है।
  • अपवाद में सदस्य एक्सेस ऑपरेटर के साथ कुछ भी नहीं करना है "। यह न्यूनतम repro में प्रकट नहीं होता है।
  • अपवाद के साथ कुछ भी नहीं है अपवाद; न्यूनतम repro में कुछ भी शून्य नहीं है।

अब चलो कुछ और प्रयोग करें। क्या होगा अगर हम N और M कक्षाएं बनाते हैं? मैं आपको परिणाम बताऊंगा:

  • व्यवहार केवल तब होता है जब दोनों structs हैं।

हम इस बात पर चर्चा कर सकते थे कि क्या समस्या केवल तब उत्पन्न होती है जब एम कुछ अर्थों में "सीधे" स्वयं का उल्लेख करता है, या फिर "अप्रत्यक्ष" चक्र भी बग को पुन: उत्पन्न करता है। (उत्तरार्द्ध सत्य है।) और जैसा कि कोरी ने अपने जवाब में नोट किया है, हम यह भी पूछ सकते हैं कि "क्या प्रकार सामान्य होना चाहिए?" नहीं; कोई जेनरिक के साथ इस से भी अधिक प्रजननकर्ता भी कम है।

हालांकि मुझे लगता है कि हमारे पास पुनरुत्पादक की हमारी चर्चा पूरी करने के लिए पर्याप्त है और सवाल पर आगे बढ़ना है, जो "क्या यह एक बग है, और यदि ऐसा है, तो क्या?"

निश्चित रूप से यहां कुछ गड़बड़ हो गई है, और मुझे आज का समय कम करने के लिए दोषी ठहराया जाना चाहिए। यहां कुछ विचार दिए गए हैं:

  • अपने स्वयं के सदस्यों वाले structs के खिलाफ नियम स्पष्ट रूप से यहां लागू नहीं होता है। (सी # 5 विनिर्देश की धारा 11.3.1 देखें, जो कि मैं हाथ में मौजूद हूं। मुझे लगता है कि इस अनुभाग को जेनेरिक के साथ सावधानीपूर्वक पुनर्लेखन से लाभ हो सकता है; यहां कुछ भाषा थोड़ा अपरिचित है।) यदि E स्थैतिक है तो वह अनुभाग लागू नहीं होता है; यदि यह स्थैतिक नहीं है तो N<M> और M के लेआउट दोनों को गणना किए बिना गणना की जा सकती है।

  • मुझे सी # भाषा में कोई अन्य नियम नहीं है जो इस प्रकार की व्यवस्था को प्रतिबंधित करेगा।

  • यह मामला हो सकता है कि सीएलआर विनिर्देश इस प्रकार की व्यवस्था को प्रतिबंधित करता है, और सीएलआर यहां अपवाद फेंकने का अधिकार है।

तो अब हम संभावनाओं को पूरा करते हैं:

  • सीएलआर में एक बग है। इस प्रकार की टोपोलॉजी कानूनी होनी चाहिए, और यहां सीएलआर को फेंकना गलत है।

  • सीएलआर व्यवहार सही है। इस प्रकार की टोपोलॉजी अवैध है, और यहां फेंकने के लिए सीएलआर का सही है। (इस परिदृश्य में यह हो सकता है कि सीएलआर में एक स्पेस बग है, इस तथ्य को विनिर्देश में पर्याप्त रूप से समझाया नहीं जा सकता है। मेरे पास आज सीएलआर स्पेक डाइविंग करने का समय नहीं है।)

आइए हम तर्क के लिए मान लें कि दूसरा सत्य है। अब हम सी # के बारे में क्या कह सकते हैं? कुछ संभावनाएं:

  • सी # भाषा विनिर्देश इस कार्यक्रम को प्रतिबंधित करता है, लेकिन कार्यान्वयन इसे अनुमति देता है। कार्यान्वयन में एक बग है। (मुझे विश्वास है कि यह परिदृश्य गलत होगा।)

  • सी # भाषा विनिर्देश इस कार्यक्रम को प्रतिबंधित नहीं करता है, लेकिन इसे उचित कार्यान्वयन लागत पर ऐसा करने के लिए बनाया जा सकता है। इस परिदृश्य में सी # विनिर्देश गलती पर है, इसे ठीक किया जाना चाहिए, और कार्यान्वयन को मैच के लिए तय किया जाना चाहिए।

  • सी # भाषा विनिर्देश कार्यक्रम को प्रतिबंधित नहीं करता है, लेकिन संकलन समय पर समस्या का पता लगाने उचित लागत पर नहीं किया जा सकता है। यह किसी भी रनटाइम क्रैश के साथ मामला है; आपका प्रोग्राम रनटाइम पर दुर्घटनाग्रस्त हो गया क्योंकि संकलक आपको एक छोटी गाड़ी प्रोग्राम लिखने से नहीं रोक सकता था। यह सिर्फ एक और छोटी गाड़ी कार्यक्रम है; दुर्भाग्यवश, आपके पास यह जानने का कोई कारण नहीं था कि यह छोटी थी।

संक्षेप में, हमारी संभावनाएं हैं:

  • सीएलआर में एक बग है
  • सी # spec एक बग है
  • सी # कार्यान्वयन में एक बग है
  • कार्यक्रम में एक बग है

इन चारों में से एक सच होना चाहिए। मुझे नहीं पता कि यह कौन सा है। क्या मुझे अनुमान लगाने के लिए कहा गया था, मैं पहले व्यक्ति को चुनूंगा; मुझे कोई कारण नहीं दिख रहा है कि सीएलआर प्रकार लोडर को इस पर क्यों झुकना चाहिए। लेकिन शायद एक अच्छा कारण है कि मुझे नहीं पता; उम्मीद है कि सीएलआर प्रकार लोडिंग सेमेन्टिक्स पर एक विशेषज्ञ इसमें शामिल होगा।

अद्यतन करें:

इस मुद्दे को यहां ट्रैक किया गया है:

https://github.com/dotnet/roslyn/issues/10126

उस मुद्दे में सी # टीम के निष्कर्षों को पूरा करने के लिए:

  • कार्यक्रम सीएलआई और सी # विनिर्देशों के अनुसार कानूनी है।
  • सी # 6 कंपाइलर प्रोग्राम की अनुमति देता है, लेकिन सीएलआई के कुछ कार्यान्वयन एक प्रकार के लोड अपवाद फेंक देते हैं। यह उन कार्यान्वयन में एक बग है।
  • सीएलआर टीम बग से अवगत है, और जाहिर है कि छोटी गाड़ी कार्यान्वयन पर ठीक करना मुश्किल है।
  • सी # टीम कानूनी कोड को चेतावनी देने पर विचार कर रही है, क्योंकि यह कुछ लोगों पर रनटाइम पर असफल हो जाएगी, लेकिन सभी नहीं, सीएलआई के संस्करण।

सी # और सीएलआर टीम इस पर हैं; उनके साथ पालन करें। यदि आपको इस मुद्दे के साथ कोई और चिंता है तो कृपया ट्रैकिंग समस्या पर पोस्ट करें, यहां नहीं।

c# visual-studio-2015 roslyn compiler-bug coreclr

मुझे लगता है कि यह एक कंपाइलर बग है।

वीएस 2015 के साथ संकलित होने पर निम्नलिखित कंसोल एप्लिकेशन संकलित रूप से निष्पादित करता है:

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            var x = MyStruct.Empty;
        }

        public struct MyStruct
        {
            public static readonly MyStruct Empty = new MyStruct();
        }
    }
}

लेकिन अब यह अजीब हो रहा है: यह कोड संकलित करता है, लेकिन निष्पादित होने पर यह TypeLoadException फेंकता है।

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            var x = MyStruct.Empty;
        }

        public struct MyStruct
        {
            public static readonly MyStruct? Empty = null;
        }
    }
}

क्या आपको एक ही समस्या का अनुभव है? यदि ऐसा है, तो मैं माइक्रोसॉफ्ट में एक मुद्दा फाइल करूंगा।

कोड बेवकूफ दिखता है, लेकिन मैं इसे पठनीयता में सुधार करने और असंबद्धता प्राप्त करने के लिए उपयोग करता हूं।

मेरे पास अलग-अलग अधिभार जैसे विधियां हैं

void DoSomething(MyStruct? arg1, string arg2)

void DoSomething(string arg1, string arg2)

इस तरह से एक विधि बुला रहा है ...

myInstance.DoSomething(null, "Hello world!")

... संकलित नहीं करता है।

कॉलिंग

myInstance.DoSomething(default(MyStruct?), "Hello world!")

या

myInstance.DoSomething((MyStruct?)null, "Hello world!")

काम करता है, लेकिन बदसूरत लग रहा है। मैं इसे इस तरह से पसंद करता हूं:

myInstance.DoSomething(MyStruct.Empty, "Hello world!")

अगर मैं Empty चर को किसी अन्य वर्ग में डालता हूं, तो सबकुछ ठीक काम करता है:

public static class MyUtility
{
    public static readonly MyStruct? Empty = null;
}

अजीब व्यवहार, है ना?

अद्यतन 2016-03-29

मैंने यहां एक टिकट खोला: http://github.com/dotnet/roslyn/issues/10126

अद्यतन 2016-04-06

यहां एक नया टिकट खोला गया है: https://github.com/dotnet/coreclr/issues/4049



Related