2015-12-24 5 views
8

मैं समझता हूं कि .NET में, अंतिम वस्तुएं तब भी चलती हैं जब कोई ऑब्जेक्ट आंशिक रूप से निर्मित होता है (उदाहरण के लिए यदि उसके कन्स्ट्रक्टर से अपवाद फेंक दिया गया हो), लेकिन जब निर्माता कभी भी नहीं चला था तो क्या होगा?.NET में, क्या किसी ऑब्जेक्ट का कन्स्ट्रक्टर कभी नहीं चलाया जाता है, भले ही फाइनलर चलाया जा सके?

पृष्ठभूमि

मैं कुछ C++/CLI कोड है कि प्रभावी रूप से निम्नलिखित करता है (मैं नहीं मानता कि यह C++/CLI सटीक है, लेकिन इस स्थिति मैं तैयार पर है):

try { 
    ClassA ^objA = FunctionThatReturnsAClassA(); 
    ClassB ^objB = gcnew ClassB(objA); // ClassB is written in C# in a referenced project 
    ... 
} 
catch (...) {...} 

मैं एक 100% दोहराने योग्य मामले में जहां, अगर एक अपवाद FunctionThatReturnsAClassA() से बाहर निकाल दिया जाता है, और फिर एक जीसी शुरू हो रहा है (इस कोड को फिर से चल रहा है, लेकिन इंतजार कर थोड़ी देर के भी काम करता है द्वारा मज़बूती से शुरू किया जा रहा है) , क्लासबी के फाइनलाइज़र को बुलाया जाता है।

अब, ट्रेस आउटपुट के माध्यम से मैं पुष्टि कर सकता हूं कि क्लासबी का कन्स्ट्रक्टर नहीं चल रहा है (जो निश्चित रूप से आप अपेक्षा करते हैं)। तो किसी भी तरह, ओबीजेबी को जाहिर तौर पर आवंटित किया गया था और अंतिम निर्माता सूची में जोड़ा गया था, इससे पहले कि उसके कन्स्ट्रक्टर को कॉल करने के लिए पूर्व शर्तएं पूरी की गईं (यानी फंक्शन थैटरनेट्सएलास्सा() से परिणाम एकत्रित करना)।

यह केवल डीबगर के बाहर चलने वाले अनुकूलित रिलीज में होता है। ऐसे कई छोटे बदलाव हैं जो परिणामस्वरूप अंतिम रूप से नहीं चल रहे हैं - उदाहरण के लिए दो कथनों के बीच एक और विधि कॉल डालना, या (बताओ, मुझे लगता है) "जीसीएनयू क्लासबी" को एक अलग फ़ंक्शन में ले जा रहा है जो लौटाता है वस्तु।

यह है कि किसी तरह gcnew बयान के आवंटन हिस्सा पुनर्क्रमित है हो रही है और पिछले बयान से पहले चलाने के लिए, लेकिन यह पुनर्व्यवस्था उत्पन्न MSIL कोड में प्रतिबिंबित नहीं होता मुझे लगता है (मेरी प्रारंभिक धारणा को हराने कि यह सिर्फ एक और C था ++/सीएलआई कोड जेन बग)। इसके अलावा, जेनरेट एमएसआईएल कोड की तुलना "बग्गी" राज्य और किसी भी "निश्चित" राज्यों के बीच तुलना में कोई अप्रत्याशित संरचनात्मक परिवर्तन नहीं दिखाती है।

मैंने डीबगर में जेनरेट किए गए x86 कोड को भी देखा है और यह अब तक अजीब नहीं दिख रहा है, लेकिन मैंने इसे गहराई से विश्लेषण नहीं किया है और फिर भी मैं इस व्यवहार को डीबगर में पुन: उत्पन्न नहीं कर सकता मुझे 100% यकीन नहीं है कि मुझे डीबगर से प्राप्त कोड कोड के समान है जो अजीब व्यवहार दिखाता है।

तो यह एक एमएसआईएल-> x86 कोड जेन क्विर्क हो सकता है या यह एक प्रोसेसर निर्देश रीडरिंग हो सकता है (पूर्व में अधिक संभावना है लेकिन व्यवहार होने पर स्मृति में सटीक कोड प्राप्त करने के लिए कठिन प्रयास करने की पुष्टि नहीं हुई है - यह मेरा अगला कदम है)।

प्रश्न

तो यह वैध (एक बेहतर शब्द की कमी के लिए) है .NET में एक वस्तु के आवंटन के लिए तलाक दे दिया और उस वस्तु के लिए निर्माता कॉल से अलग पुनर्क्रमित जा करने के लिए?

+3

के लिए एक वस्तु को फोन करके अपने निर्माताओं में से किसी को बुला के बिना आवंटित किया जाना यह संभव है [ 'FormatterServices.GetUninitializedObject()'] (https: // MSDN

यह अब एक JIT अनुकूलन बग होने की पुष्टि की है .microsoft.com/en-us/पुस्तकालय/system.runtime.serialization.formatterservices.getuninitializedobject.aspx)। इस तरह से 'बाइनरीफॉर्मेटर' और 'डेटाकंट्रैक्ट सीरिएलाइज़र' दोनों वस्तुएं बनाते हैं।बाद में, यदि ऑब्जेक्ट में फाइनलाइज़र है, तो इसे अंतिम रूप दिया जाएगा। लेकिन मुझे नहीं लगता कि आप यही देख रहे हैं, है ना? – dbc

+0

यह बिल्कुल ठीक नहीं है जो मैं देख रहा हूं लेकिन यह इस बात पर प्रकाश डाला गया है कि ढांचा इस तरह वस्तुओं को बना सकता है और कम से कम सैद्धांतिक रूप से संभव है कि आवंटन और निर्माण के बीच कुछ बाधा उत्पन्न हो सके। लेकिन, यह जवाब नहीं देता है कि मानक दो/जीसीएन्यू कथन के हिस्से के रूप में चलाने के दौरान उन दो चरणों के लिए अलग होना अलग है या नहीं। – rationull

+0

JItter अनुकूलक कीड़े हो सकती हैं। लेकिन यह नहीं, ऑब्जेक्ट आवंटन (जो अंतिम रूप से चलाने के लिए अंतिम हो जाता है) और कन्स्ट्रक्टर कॉल एक सीएलआर सहायक समारोह के लिए एक ही कॉल है। एक कॉल में पुन: क्रमिक समस्याएं नहीं हो सकती हैं। आपको दस्तावेज़ित सीएलआर संस्करण संख्या के साथ एक अच्छा रेपो की आवश्यकता होगी और आगे बढ़ने के लिए माइक्रोसॉफ्ट समर्थन के साथ टेलीफोन प्राप्त करें। –

उत्तर

1

टिप्पणियों में शामिल होने के रूप में, जवाब "हां" है - एक कन्स्ट्रक्टर चलाया जा सकता है यदि कोई कन्स्ट्रक्टर नहीं चला या पूरा नहीं हुआ। हालांकि एक आवंटन तब नहीं चलाया जा सकता है जब आवंटन नहीं हुआ (जो कि कन्स्ट्रक्टर कॉल से स्वतंत्र है)। https://github.com/dotnet/coreclr/issues/2478

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

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