2013-02-22 8 views
6

Wenn Sie einen Zeiger wie int* in C# verwenden, müssen Sie das Schlüsselwort unsafe verwenden, aber wenn Sie eine IntPtr verwenden, tun Sie dies nicht. Was ist der Unterschied von diesen? Sie können beide auf eine Adresse zeigen.Warum benötigt IntPtr nicht das unsichere Schlüsselwort?

Wie geht der Garbage Collector mit diesen beiden Typen um? Werden sie anders behandelt? Wenn ja, worin besteht der Unterschied? Wenn nicht, warum benötigt man das Schlüsselwort unsafe?

Edit: Vielen Dank für Antworten der jeder so weit, aber was ich möchte, ist wissen, wie sie unterschiedlich vom Framework behandelt werden und der Garbage Collector, anstatt die MSDN Definition von IntPtr. Es braucht nur eine Google-Suche, um dorthin zu gelangen. Was würde ich gerne wissen, warum IntPtr das Schlüsselwort unsafe nicht benötigt? Ich möchte den Grund verstehen, warum wir es ohne das Schlüsselwort verwenden können.

Antwort

5

Nach MSDN:

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

Es ist lediglich eine Darstellung "eines Zeigers oder eines Griffes."

Ich mache etwas zu lesen, wie die IntPtr anders durch die GC als andere verwaltete Typen behandelt wird, und ich habe keine Unterlagen oder Gegenstände unter Angabe der IntPtr gefunden anders gesammelt wird, dh sobald die IntPtr geht außerhalb des Geltungsbereichs kann GC'd sein.

Über warum gibt es keine Verwendung des unsafe Schlüsselwort lesen die akzeptierte Antwort vor allem das Update:

Does unsafe code have any effect on safe code?

unsafe bereits bei der Umsetzung der IntPtr angegeben (die Feld Erklärungen in der IntPtr Implementierung sehen (siehe unten), so dass die Klasse, die IntPtr verwendet, keine Verwendung von IntPtr als unsafe auch markieren muss, andernfalls würde sie bis zu anderen Klassen kaskadiert werden, die Typen verwenden könnten, die unsicheren Code in ihrer Implementierung haben.

Neben dem unsafe-Code ist nicht IntPtr, es ist das Feld private unsafe void* m_value; die unsafe ist und Sie verwenden es nicht direkt.

// 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 ist ein Werttyp. Es handelt sich nicht um den gesammelten oder vom Kollektor behandelten Müll. Es ist nur eine Werttypnummer, die so groß wie die native Zeigergröße ist. –

1

IntPtr ist ein verwalteter Typ und wird verwendet, d. H. Um native Handles des Windows-Betriebssystems zu erhalten. Sie sollten es nicht mit einem tatsächlichen Zeiger wie int* verwechseln.

Weitere Informationen finden Sie unter MSDN.

+0

'IntPtr' stellt' void * 'und nicht die OS-Anbieter bezogen und warum es zu/von Methoden dafür. – leppie

+0

@leppie Ja, Sie haben Recht, obwohl es 'void *' ist, stellt es normalerweise eine positive Zahl in Windows dar. –

1

Ein IntPtr ist im Wesentlichen nur eine verwaltete Darstellung eines Zeigertyps. Sie können beliebige Zeigertypen in einem unsicheren Kontext frei auf IntPtr umwandeln. Im Wesentlichen ein IntPtr ist nur ein dünner Wrapper um eine void* (IIRC enthält ein privates Feld void*).

Es ist häufig während interop mit nicht verwalteten Code (via PInvoke oder Marshal Klasse) als in-place Ersatz für nicht verwalteten Zeigertypen wie, wie Zeiger, ein IntPtr ‚s Größe variiert mit der Architektur (4 Byte auf einem x86-System, 8 auf einem x64).

0

Eine verwandte Frage ... Warum benötigt dllimport keinen unsicheren Kontext?

Ich vermute, der Grund, dass IntPtr und dllimport keinen unsicheren Kontext erfordern, ist, VB.NET (das nicht unsicher ist) zu aktivieren, um leicht auf native APIs zuzugreifen.

Allerdings gibt es sicherlich etwas "unsicheres" über dllimport, IntPtr und ihre Interaktion.

Die Übergabe ungültiger Argumente an einen Dllimport-Einstiegspunkt kann einen Absturz verursachen oder schlimmer noch den Speicher beschädigen. Dies bedeutet, dass jeder Code, der einen dllimport macht, in meinen Augen "unsicher" ist. Wenn dieser Code einen IntPtr aus dem Sicherheitscode in den Dllimport-Einstiegspunkt leckt, wird im Wesentlichen die "Unsicherheit" in diesen sicheren Code ausgeleert, da der Sicherheitscode das IntPtr so ändern könnte, dass es ungültig wird.

Wenn ich dllimport verwende, bevorzuge ich lieber Zeiger als unsafe-struct Zeiger statt IntPtr. Dies hat zwei große Vorteile. Erstens gibt es mir eine Typüberprüfung für verschiedene Arten von nativen Zeigern. Zweitens verhindert es, dass gefährliche nicht verwaltete native Zeiger in "sicheren" Code gelangen.

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

Verwandte Themen