2013-02-22 118 views
6

当您在C#中使用类似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由GC比其他托管类型不同的方式处理一些阅读,我还没有发现任何文件或物品陈述IntPtr收集任何区别,即,只要IntPtr去超出范围它可以被GC'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是一个值类型。它不是收集器收集或处理的垃圾。它只是一个值型数字,与原生指针大小一样大。 – 2016-07-03 04:27:19

1

IntPtr是一种托管类型,用于获取Windows操作系统的本机句柄。您不应该将它与实际指针混淆,如int*

请参阅MSDN作进一步参考。

+0

'IntPtr'代表'无效*',而不是OS供应商相关的,以及为什么有向/从它的方法。 – leppie 2013-02-22 11:08:04

+0

@leppie是的,你说得对,虽然它是'void *',它通常代表Windows中的一个正数。 – 2013-02-22 11:10:29

1

一种IntPtr本质上只是一个指针类型的管理表示。您可以在不安全的环境中自由地将任何指针类型转换为IntPtr。本质上,IntPtr只是一个围绕void*(IIRC它包含专用void*字段)的薄包装。

它与非托管代码的互操作过程中是常见的(经由PInvokeMarshal类)作为就地替代非托管指针类型如,例如指针,一个IntPtr的尺寸与结构变化(一个x86的系统的4个字节上, 8在x64上)。

0

相关问题...为什么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

相关问题