Why doesn't IntPtr need the unsafe keyword?

When you use an int* pointer in C #, you need to use the unsafe keyword, but when you use IntPtr , you do not. What is their difference? They can both point to an address.

How does the garbage collector handle these two types? Is it different with them? If so, what is the difference? If not, why do you need the unsafe keyword?

Edit: Thank you very much for the answers to all the answers, but I would like to know how they are handled differently using the framework and the garbage collector, not the MSDN IntPtr definition. This requires only one Google search. What would I like to know why IntPtr does not need an unsafe key? I would like to understand the reason why we can use it without a keyword.

+6
source share
4 answers

According to MSDN:

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

It is simply a pointer or descriptor representation.

I was doing some reading about how GC IntPtr handles GC differently than other managed types, and I have not found any documentation or articles in which IntPtr text is collected in any other way, that is, as soon as IntPtr goes beyond visibility, he may be gc'd.

About why the unsafe keyword is not used, read the accepted answer, especially the update:

Wrong code affects safe code?

unsafe already specified in the IntPtr implementation (see the field descriptions in the IntPtr implementation below), therefore a class using IntPtr should not mark the use of IntPtr it also uses as unsafe , otherwise it will be cascaded up to other classes that can use types in which unsafe code.

In addition, unsafe code is not IntPtr , this is a private unsafe void* m_value; equals unsafe , and you are not using it directly.

 // 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; } } } 
+5
source

IntPtr is a managed type and is used, i.e. to get your own Windows OS descriptors. You should not confuse it with the actual pointer, for example int* .

See MSDN for more details.

+1
source

An IntPtr is just a managed representation of a pointer type. You can freely apply any type of pointer to IntPtr in an insecure context. Essentially, IntPtr is just a thin shell around void* (IIRC contains the private field void* ).

This is usually during interaction with unmanaged code (via the PInvoke or Marshal class) as an in-place replacement for unmanaged pointer types, since, for example, pointers, the size of IntPtr depends on the architecture (4 bytes on x86, 8 on x64).

+1
source

Related question ... Why does dllimport not require an insecure context?

I suspect that the reason IntPtr and dllimport do not require an insecure context is to allow VB.NET (which is not insecure) to easily access its own APIs.

However, there is something โ€œunsafeโ€ regarding dllimport, IntPtr and their interactions.

Passing invalid arguments to the dllimport entry point can cause a crash or, even worse, corrupted memory. This means that any code that dllimport runs is in my opinion "unsafe." Also, if this IntPtr code leaked from the safe code to the dllimport entry point, it essentially leaked the โ€œsafeโ€ code into this safe code, because the safe code could modify IntPtr to invalidate it.

When I use dllimport, I prefer to enter pointers as pointers to an unsafe structure, rather than IntPtr. This has two big advantages. First, it gives me type checking for different types of internal pointers. Secondly, it prevents the leakage of dangerous unmanaged pointers to "safe" code.

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

0
source

All Articles