簡體   English   中英

為什么IntPtr不需要unsafe關鍵字?

[英]Why doesn't IntPtr need the unsafe keyword?

在C#中使用像int*這樣的指針時,需要使用unsafe關鍵字,但是在使用IntPtr ,則不需要。 這些有什么區別? 他們倆都可以指向一個地址。

垃圾收集器如何處理這兩種類型? 他們的處理方式不同嗎? 如果是這樣,有什么區別? 如果不是,為什么需要unsafe關鍵字?

編輯:到目前為止,非常感謝大家的回答,但是我想知道的是框架和垃圾收集器如何不同地處理它們,而不是IntPtr的MSDN定義。 只需進行一次Google搜索即可。 我想知道為什么IntPtr不需要unsafe關鍵字? 我想了解沒有關鍵字就可以使用它的原因。

根據MSDN:

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

它僅是“指針或句柄”的表示

我一直在閱讀有關GC與其他托管類型如何不同地處理IntPtr ,並且我還沒有發現任何說明IntPtr的收集方式有所不同的文檔或文章,即,一旦IntPtr超出范圍,它可以被GC。

關於為什么不使用unsafe關鍵字的原因,請閱讀已接受的答案,尤其是更新內容:

不安全代碼對安全代碼有影響嗎?

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;
    }
  }
}

IntPtr是一種托管類型,用於,即獲取Windows OS的本機句柄。 您不應將其與int*這樣的實際指針混淆。

有關更多參考,請參見MSDN

IntPtr本質上只是指針類型的托管表示形式。 您可以在不安全的上下文中將任何指針類型自由轉換為IntPtr 本質上, IntPtr只是圍繞void* (IIRC它包含一個私有void*字段)的薄包裝。

通常在與非托管代碼(通過PInvokeMarshal類)進行互操作期間作為非托管指針類型的就地替換,因為就像指針一樣, IntPtr的大小隨體系結構而有所不同(x86系統上為4個字節,x64系統上為8個字節) )。

一個相關問題...為什么dllimport不需要不安全的上下文?

我懷疑IntPtr和dllimport不需要不安全上下文的原因是使VB.NET(沒有不安全)可以輕松訪問本機API。

但是,對於dllimport,IntPtr及其交互,肯定存在某些“不安全”之處。

將無效的參數傳遞給dllimport入口點可能會導致崩潰,或更糟糕的是,無提示地破壞內存。 這意味着在我看來,任何執行dllimport的代碼都是“不安全的”。 此外,如果該代碼將IntPtr從安全代碼泄漏到dllimport入口點,則實質上是在安全代碼中泄漏了“不安全”,因為安全代碼可以修改IntPtr使其無效。

當我使用dllimport時,我更喜歡將指針鍵入為unsafe-struct指針,而不是IntPtr。 這有兩個好處。 首先,它使我可以檢查不同類型的本機指針的類型。 其次,它可以防止危險的非托管本機指針泄漏到“安全”代碼中。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM