2013-02-22 19 views
6

जब आप सी # में int* जैसे पॉइंटर का उपयोग करते हैं, तो आपको unsafe कीवर्ड का उपयोग करने की आवश्यकता है, लेकिन जब आप IntPtr का उपयोग करते हैं, तो आप नहीं करते हैं। इनका क्या अंतर है? वे दोनों एक पते को इंगित कर सकते हैं।IntPtr को असुरक्षित कीवर्ड की आवश्यकता क्यों नहीं है?

कचरा कलेक्टर इन दो प्रकारों से कैसे निपटता है? क्या वे अलग-अलग व्यवहार कर रहे हैं? यदि हां, तो क्या अंतर है? यदि नहीं, तो किसी को unsafe कीवर्ड क्यों चाहिए?

संपादित करें: हर किसी का जवाब के लिए धन्यवाद एक बहुत अब तक, लेकिन मैं क्या जानना चाहते हैं कि वे किस तरह ढांचे और कचरा कलेक्टर, बजाय IntPtr की MSDN परिभाषा से अलग ढंग से नियंत्रित किया जाता है है। यह वहां जाने के लिए केवल एक Google खोज लेता है। मैं क्या जानना चाहता हूं कि IntPtr को unsafe कीवर्ड की आवश्यकता क्यों नहीं है? मैं इस कारण को समझना चाहता हूं कि हम कीवर्ड के बिना इसका उपयोग क्यों कर सकते हैं।

उत्तर

5

MSDN के अनुसार:

http://msdn.microsoft.com/en-gb/library/system.intptr(v=vs.100).aspx

यह केवल की एक प्रतिनिधित्व कि "एक सूचक या एक हैंडल।"

मैं, कैसे IntPtr अन्य कामयाब प्रकार से जी सी द्वारा अलग ढंग से नियंत्रित किया जाता है पर कुछ पढ़ने कर दिया गया है, और मैं नहीं मिला है किसी भी दस्तावेज या लेख IntPtr बताते हुए इकट्ठा किया जाता है किसी भी अलग ढंग से, यानी जैसे ही IntPtr चला जाता है के रूप में दायरे से बाहर यह जीसी'd किया जा सकता है।

बारे में क्यों unsafe कीवर्ड का कोई उपयोग नहीं है स्वीकार किए जाते हैं जवाब विशेष रूप से अद्यतन पढ़ें:

Does unsafe code have any effect on safe code?

unsafe पहले से ही IntPtr के कार्यान्वयन में निर्दिष्ट किया गया है (IntPtr कार्यान्वयन में क्षेत्र घोषणाओं देखना नीचे), इसलिए IntPtr का उपयोग करने वाले वर्ग को IntPtr के किसी भी उपयोग को चिह्नित करने की आवश्यकता नहीं है, यह unsafe के रूप में भी उपयोग करता है, अन्यथा इसे अन्य वर्गों तक कैस्केड किया जाएगा जो उनके कार्यान्वयन में असुरक्षित कोड वाले प्रकारों का उपयोग कर सकते हैं।

unsafe कोड इसके अलावा IntPtr नहीं है, यह क्षेत्र private unsafe void* m_value; कि है unsafe है और आप इसे सीधे उपयोग नहीं कर रहे।

// Type: System.IntPtr 
// Assembly: mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 
// Assembly location: C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscorlib.dll 

using System.Globalization; 
using System.Runtime; 
using System.Runtime.ConstrainedExecution; 
using System.Runtime.InteropServices; 
using System.Runtime.Serialization; 
using System.Security; 

namespace System 
{ 
    [ComVisible(true)] 
    [__DynamicallyInvokable] 
    [Serializable] 
    public struct IntPtr : ISerializable 
    { 
    [SecurityCritical] 
    private unsafe void* m_value; 
    public static readonly IntPtr Zero; 

    [__DynamicallyInvokable] 
    public static int Size 
    { 
     [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success), TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries"), __DynamicallyInvokable] get 
     { 
     return 4; 
     } 
    } 

    [SecuritySafeCritical] 
    [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")] 
    [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)] 
    [__DynamicallyInvokable] 
    public IntPtr(int value) 
    { 
     this.m_value = (void*) value; 
    } 

    [SecuritySafeCritical] 
    [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")] 
    [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)] 
    [__DynamicallyInvokable] 
    public IntPtr(long value) 
    { 
     this.m_value = (void*) checked ((int) value); 
    } 

    [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)] 
    [SecurityCritical] 
    [CLSCompliant(false)] 
    [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] 
    public IntPtr(void* value) 
    { 
     this.m_value = value; 
    } 

    [SecurityCritical] 
    private IntPtr(SerializationInfo info, StreamingContext context) 
    { 
     long int64 = info.GetInt64("value"); 
     if (IntPtr.Size == 4 && (int64 > (long) int.MaxValue || int64 < (long) int.MinValue)) 
     throw new ArgumentException(Environment.GetResourceString("Serialization_InvalidPtrValue")); 
     this.m_value = (void*) int64; 
    } 

    [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)] 
    [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")] 
    public static explicit operator IntPtr(int value) 
    { 
     return new IntPtr(value); 
    } 

    [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")] 
    [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)] 
    public static explicit operator IntPtr(long value) 
    { 
     return new IntPtr(value); 
    } 

    [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")] 
    [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)] 
    [SecurityCritical] 
    [CLSCompliant(false)] 
    public static explicit operator IntPtr(void* value) 
    { 
     return new IntPtr(value); 
    } 

    [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")] 
    [SecuritySafeCritical] 
    [CLSCompliant(false)] 
    public static explicit operator void*(IntPtr value) 
    { 
     return value.ToPointer(); 
    } 

    [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")] 
    [SecuritySafeCritical] 
    public static explicit operator int(IntPtr value) 
    { 
     return (int) value.m_value; 
    } 

    [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")] 
    [SecuritySafeCritical] 
    public static explicit operator long(IntPtr value) 
    { 
     return (long) (int) value.m_value; 
    } 

    [SecuritySafeCritical] 
    [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] 
    [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")] 
    public static bool operator ==(IntPtr value1, IntPtr value2) 
    { 
     return value1.m_value == value2.m_value; 
    } 

    [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] 
    [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")] 
    [SecuritySafeCritical] 
    public static bool operator !=(IntPtr value1, IntPtr value2) 
    { 
     return value1.m_value != value2.m_value; 
    } 

    [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")] 
    [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)] 
    public static IntPtr operator +(IntPtr pointer, int offset) 
    { 
     return new IntPtr(pointer.ToInt32() + offset); 
    } 

    [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")] 
    [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)] 
    public static IntPtr operator -(IntPtr pointer, int offset) 
    { 
     return new IntPtr(pointer.ToInt32() - offset); 
    } 

    [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] 
    [SecuritySafeCritical] 
    internal unsafe bool IsNull() 
    { 
     return (IntPtr) this.m_value == IntPtr.Zero; 
    } 

    [SecurityCritical] 
    unsafe void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) 
    { 
     if (info == null) 
     throw new ArgumentNullException("info"); 
     info.AddValue("value", (long) (int) this.m_value); 
    } 

    [SecuritySafeCritical] 
    [__DynamicallyInvokable] 
    public override unsafe bool Equals(object obj) 
    { 
     if (obj is IntPtr) 
     return this.m_value == ((IntPtr) obj).m_value; 
     else 
     return false; 
    } 

    [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")] 
    [SecuritySafeCritical] 
    [__DynamicallyInvokable] 
    public override unsafe int GetHashCode() 
    { 
     return (int) this.m_value; 
    } 

    [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")] 
    [SecuritySafeCritical] 
    [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] 
    [__DynamicallyInvokable] 
    public unsafe int ToInt32() 
    { 
     return (int) this.m_value; 
    } 

    [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")] 
    [SecuritySafeCritical] 
    [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] 
    [__DynamicallyInvokable] 
    public unsafe long ToInt64() 
    { 
     return (long) (int) this.m_value; 
    } 

    [SecuritySafeCritical] 
    [__DynamicallyInvokable] 
    public override unsafe string ToString() 
    { 
     return ((int) this.m_value).ToString((IFormatProvider) CultureInfo.InvariantCulture); 
    } 

    [SecuritySafeCritical] 
    [__DynamicallyInvokable] 
    public unsafe string ToString(string format) 
    { 
     return ((int) this.m_value).ToString(format, (IFormatProvider) CultureInfo.InvariantCulture); 
    } 

    [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)] 
    [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")] 
    public static IntPtr Add(IntPtr pointer, int offset) 
    { 
     return pointer + offset; 
    } 

    [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")] 
    [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)] 
    public static IntPtr Subtract(IntPtr pointer, int offset) 
    { 
     return pointer - offset; 
    } 

    [SecuritySafeCritical] 
    [CLSCompliant(false)] 
    [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] 
    [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")] 
    public unsafe void* ToPointer() 
    { 
     return this.m_value; 
    } 
    } 
} 
+0

IntPtr एक मान प्रकार है। यह कलेक्टर द्वारा एकत्रित या संभाला कचरा नहीं है। यह सिर्फ एक मूल्य-प्रकार संख्या है, जो देशी सूचक आकार जितना बड़ा है। –

1

IntPtr एक प्रबंधित प्रकार है और इसका उपयोग किया जाता है, यानी विंडोज ओएस के देशी हैंडल प्राप्त करने के लिए। आपको int* जैसे वास्तविक पॉइंटर से भ्रमित नहीं करना चाहिए।

आगे संदर्भ के लिए MSDN देखें।

+0

'' IntPtr' शून्य * 'और नहीं ओएस-विक्रेता संबंधित का प्रतिनिधित्व करता है और क्यों यह करने के लिए तरीके से करने के लिए/देखते हैं। – leppie

+0

@leppie हां, आप सही हैं, फिर भी, हालांकि 'शून्य * होने के कारण यह आमतौर पर विंडोज में एक सकारात्मक संख्या का प्रतिनिधित्व करता है। –

1

एक IntPtr अनिवार्य रूप से एक सूचक प्रकार के सिर्फ एक कामयाब प्रतिनिधित्व है। आप असुरक्षित संदर्भ में IntPtr पर किसी भी सूचक प्रकार को स्वतंत्र रूप से कास्ट कर सकते हैं। अनिवार्य रूप से IntPtrvoid* (आईआईआरसी में एक निजी void* फ़ील्ड) के आस-पास एक पतला आवरण है।

यह रूप में अप्रबंधित सूचक प्रकार, संकेत की तरह के लिए एक में जगह स्थानापन्न के रूप में अप्रबंधित कोड के साथ इंटरॉप दौरान आमतौर पर है (PInvoke या Marshal वर्ग के माध्यम से), एक IntPtr के आकार, एक 86 सिस्टम पर 4 बाइट (वास्तुकला के साथ बदलता रहता 8 x64 पर)।

0

एक संबंधित प्रश्न ... डेलिमपोर्ट को असुरक्षित संदर्भ की आवश्यकता क्यों नहीं है?

मुझे संदेह है कि IntPtr और dllimport को असुरक्षित संदर्भ की आवश्यकता नहीं है, मूल एपीआई को आसानी से एक्सेस करने के लिए VB.NET (जो असुरक्षित नहीं है) को सक्षम करने के लिए है।

हालांकि, निश्चित रूप से डिलिमपोर्ट, इंटिप्टर और उनकी बातचीत के बारे में कुछ "असुरक्षित" है।

एक dllimport एंट्री पॉइंट में अमान्य तर्कों को सौंपना एक क्रैश, या बदतर, चुपचाप भ्रष्ट स्मृति का कारण बन सकता है। इसका मतलब है कि कोई भी कोड जो dllimport करता है मेरे दिमाग में "असुरक्षित" है। इसके अलावा, यदि वह कोड सुरक्षित कोड से डीएलआईएमपोर्ट एंट्री पॉइंट में इंटिप्रेट को लीक करता है, तो यह अनिवार्य रूप से उस सुरक्षित कोड में "असुरक्षित" बाहर निकल जाता है, क्योंकि सुरक्षित कोड इंटिप्ट को इसे अमान्य बनाने में संशोधित कर सकता है।

जब मैं डिलिमपोर्ट का उपयोग करता हूं, तो मैं इंटिप्रेट की बजाय पॉइंटर्स को असुरक्षित-संरचना पॉइंटर्स के रूप में टाइप करना पसंद करता हूं। इसमें दो बड़े लाभ हैं। सबसे पहले, यह मुझे विभिन्न प्रकार के देशी पॉइंटर्स के लिए टाइप-चेकिंग देता है। दूसरा, यह खतरनाक अप्रबंधित देशी पॉइंटर्स को "सुरक्षित" कोड में लीक करने से रोकता है।

http://www.codeproject.com/script/Articles/ArticleVersion.aspx?aid=339290&av=638710

http://software.1713.n2.nabble.com/using-unsafe-struct-instead-of-IntPtr-with-PInvoke-td5861023.html

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