2010-12-23 7 views
5

निम्नलिखित कोड पर विचार करें:इस तरह की स्ट्रिंग की सामग्री को बदलना एक अपवाद का कारण बनना चाहिए?

using System; 
using System.Runtime.InteropServices; 

namespace Demo 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      const string test = "ABCDEF"; // Strings are immutable, right? 
      char[] chars = new StringToChar{str=test}.chr; 
      chars[0] = 'X'; 

      // On an x32 release or debug build or on an x64 debug build, 
      // the following prints "XBCDEF". 
      // On an x64 release build, it prints "ABXDEF". 
      // In both cases, we have changed the contents of 'test' without using 
      // any 'unsafe' code... 

      Console.WriteLine(test); 
     } 
    } 

    [StructLayout(LayoutKind.Explicit)] 
    public struct StringToChar 
    { 
     [FieldOffset(0)] 
     public string str; 
     [FieldOffset(0)] 
     public char[] chr; 
    } 
} 

इस कोड को चला कर, हम एक अपवाद घटित बिना एक स्ट्रिंग की सामग्री को बदलने में सक्षम हैं। ऐसा करने के लिए हमें किसी भी असुरक्षित कोड की घोषणा करने की आवश्यकता नहीं थी। यह कोड स्पष्ट रूप से बहुत डोडी है!

मेरा प्रश्न यह है कि: क्या आपको लगता है कि ऊपर दिए गए कोड द्वारा एक अपवाद फेंक दिया जाना चाहिए?

[EDIT1: ध्यान दें कि अन्य लोगों को मेरे लिए यह कोशिश की है, और कुछ लोगों अलग परिणाम प्राप्त - जो भी मैं क्या कर रहा हूं की nastyness नहीं दिया आश्चर्य की बात है ...;)]

[ EDIT2: ध्यान दें कि मैं दृश्य स्टूडियो 2010 का उपयोग कर रहा विंडोज 7 पर अंतिम 64 बिट]

[EDIT3: परीक्षण स्ट्रिंग स्थिरांक बने, बस बनाने के लिए यह और भी कुशल]

+2

[प्रश्न जो मैंने पहले से पूछा है] का डुप्लिकेट (http://stackoverflow.com/questions/792735/why-does-this-code-work-without-the-unsafe-keyword) :-) –

+0

बहुत रोचक! ऐसा लगता है कि यह एक प्रसिद्ध समस्या है। –

उत्तर

3

मेरा वोट के FieldOffset असुरक्षित बनाने पर! ।

+0

हां, यह पूरी तरह से उपयुक्त प्रतीत होता है! –

5

clr/src/vm/class.cpp के लिए एसएससीएलआई 20 स्रोत कोड, विधिटेबलबिल्डर :: हैंडलएक्सप्लिटलाइट कुछ अंतर्दृष्टि प्रदान कर सकता है। यह असामान्य रूप से भारी टिप्पणी की है, इस टिप्पणी नियमों का वर्णन करता है (पठनीयता के लिए संपादित):

// go through each field and look for invalid layout 
// (note that we are more permissive than what Ecma allows. We only disallow 
// the minimum set necessary to close security holes.) 
// 
// This is what we implement: 
// 
// 1. Verify that every OREF is on a valid alignment 
// 2. Verify that OREFs only overlap with other OREFs. 
// 3. If an OREF does overlap with another OREF, the class is marked unverifiable. 
// 4. If an overlap of any kind occurs, the class will be marked NotTightlyPacked (affects ValueType.Equals()). 

नियम 1 सुनिश्चित करता है कि एक संदर्भ काम परमाणु रहता है। नियम 2 कहता है कि आप जो भी कर सकते हैं वह कर सकते हैं, किसी ऑब्जेक्ट प्रकार का संदर्भ ओवरलैप हो सकता है। एक मूल्य प्रकार मान के साथ ओवरलैप की अनुमति नहीं है, जो कचरा कलेक्टर को खराब करता है। नियम 3 परिणाम बताता है, यह केवल प्रकार गैर-सत्यापन योग्य बनाता है।

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

बिंदु घर ड्राइविंग: सी # असुरक्षित कीवर्ड सीएलआर क्या सत्यापित करने योग्य नहीं है, और इस प्रकार वास्तव में सुरक्षित कोड से संबंधित नहीं है। यह पॉइंटर्स या कस्टम वैल्यू प्रकार (निश्चित) का उपयोग करके, ब्लैटेंट मामलों का ख्याल रखता है। चाहे वह सी # भाषा spec में एक रिसाव बहस योग्य है। Pinvoke अधिक स्पष्ट किनारे के मामले होने के नाते। एक ऑपरेटिंग सिस्टम फ़ंक्शन को पिनवोक करना सुंदर कुत्ता सुरक्षित है। Pinvoking कुछ तीसरे पक्ष सी पुस्तकालय नहीं है।

लेकिन मुझे @fej से सहमत होना है, [फील्डऑफसेट] को "आप निश्चित हैं" उपचार प्राप्त करना चाहिए था। बहुत बुरा है इसके लिए कोई वाक्यविन्यास नहीं है। माना जाता है कि, मुझे अभी तक पता नहीं लगा है कि इसे वास्तव में प्रबंधित लेआउट को प्रभावित करने की आवश्यकता क्यों है। यह अधिक अधिक समझ देगा कि यह विशेषता केवल मार्शल लेआउट पर लागू होगी। अजीब, किसी ने शुरुआती दिनों में अपनी आस्तीन को पकड़ लिया हो सकता है।

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