8

int*C#のようにポインターを使用する場合は、unsafeキーワードを使用する必要がありますが、を使用する場合は使用IntPtrしません。これらの違いは何ですか?どちらもアドレスを指すことができます。

ガベージコレクターはこれら2つのタイプをどのように処理しますか?彼らは異なって扱われますか?もしそうなら、違いは何ですか?そうでない場合、なぜunsafeキーワードが必要なのですか?

編集:これまでの皆さんの回答に感謝しますが、私が知りたいのは、MSDNの定義ではなく、フレームワークとガベージコレクターによってそれらがどのように異なる方法で処理されるかですIntPtr。そこに行くのにたった1回のGoogle検索が必要です。IntPtrがキーワードを必要としない理由を知りたいのですがunsafe?キーワードなしで使用できる理由を把握したいと思います。

4

4 に答える 4

5

MSDNによると:

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

これは単に「ポインタまたはハンドル」の表現です。

GCによって他の管理対象タイプとは異なる方法で処理される方法について読んでいますが、収集方法が異なることIntPtrを示すドキュメントや記事は見つかりませんでした。つまり、範囲外になるとすぐにGCになる可能性があります。 'd。IntPtrIntPtr

キーワードが使用されない理由についてはunsafe、受け入れられた回答、特に更新を読んでください。

安全でないコードは安全なコードに影響を及ぼしますか?

unsafeの実装ですでに指定されているためIntPtr(以下の実装のフィールド宣言をIntPtr参照)、を使用するクラスは、その使用IntPtrをマークする必要もありません。そうしないと、他のクラスにカスケードされます。実装に安全でないコードが含まれる型を使用する場合があります。IntPtrunsafe

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;
    }
  }
}
于 2013-02-22T11:06:36.330 に答える
1

IntPtrは管理対象タイプであり、つまりWindowsOSのネイティブハンドルを取得するために使用されます。のような実際のポインタと混同しないでくださいint*

詳細については、 MSDNを参照してください。

于 2013-02-22T11:06:29.893 に答える
1

AnIntPtrは基本的に、ポインタ型の単なる管理された表現です。IntPtr安全でないコンテキストでは、任意のポインタ型をに自由にキャストできます。基本的に、anは(プライベートフィールドを含むIIRC )IntPtrの単なる薄いラッパーです。void*void*

ポインターのように、サイズはアーキテクチャーによって異なるため(x86システムでは4バイト、x64では8バイト)、アンマネージポインタータイプのインプレース置換として、アンマネージコード(PInvokeまたはクラス経由)との相互運用が一般的です。MarshalIntPtr

于 2013-02-22T11:10:36.217 に答える
1

関連する質問...dllimportが安全でないコンテキストを必要としないのはなぜですか?

IntPtrとdllimportが安全でないコンテキストを必要としない理由は、VB.NET(安全ではない)がネイティブAPIに簡単にアクセスできるようにするためだと思います。

ただし、dllimport、IntPtr、およびそれらの相互作用については確かに「安全でない」ものがあります。

無効な引数をdllimportエントリポイントに渡すと、クラッシュが発生したり、さらに悪いことに、メモリがサイレントに破損したりする可能性があります。これは、dllimportを実行するコードが私の心の中で「安全ではない」ことを意味します。さらに、そのコードがIntPtrを安全なコードからdllimportエントリポイントにリークした場合、安全なコードがIntPtrを変更して無効にする可能性があるため、本質的に「安全でない」コードがその安全なコードにリークされます。

dllimportを使用するときは、IntPtrではなくunsafe-structポインターとしてポインターを入力することを好みます。これには2つの大きな利点があります。まず、さまざまな種類のネイティブポインタの型チェックができます。次に、危険なアンマネージネイティブポインタが「安全な」コードに漏れるのを防ぎます。

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

于 2013-08-20T07:08:12.863 に答える