2009-11-10 101 views
1

因此,從我所知道的情況來看,我發現的IntPtr的每個託管示例都是錯誤IntPtr addition

例如: http://www.atalasoft.com/cs/blogs/stevehawley/archive/2006/10/16/10987.aspx

我的想法之中,如果IntPtr的是在(或接近)int32.MaxValue在32位系統上,又添加了一個偏移量溢出INT32,是不是仍然一個有效的內存地址(因爲它將在uint32中有效,並且將在IntPtr中由負數表示)?

我相信代碼應該是這樣的:

public static IntPtr Offset(IntPtr src, int offset) 
{ 
    switch (IntPtr.Size) { 
    case 4: 
     return new IntPtr((int)((uint)src + offset)); 
    case 8: 
     return new IntPtr((long)((ulong)src + offset)); 
    default: 
     throw new NotSupportedException("Not supported"); 
    } 
} 

我瘋了?

有沒有人有一個嘗試和真正的IntPtr另外的例子?

+0

我剛纔看到了.NET Framework 4.0支持IntPtrs一個新的Add方法,有沒有人使用反射來看看MS是什麼在做什麼?我沒有安裝4.0測試版的副本。 – userx 2009-11-10 20:46:44

回答

1

我認爲這一點是,如果你溢出一個int,你還是獲得適當的價值。試試這個:

//-2147483645 
Console.WriteLine(int.MaxValue + 4); 

//2147483651 
Console.WriteLine((uint)(int.MaxValue + 4)); 

鑑於int.MaxValue是2147483647,鑄造溢出負數爲uint事實上確實給出正確的值。

+0

很愚蠢,直到現在我還沒有嘗試過這種方法(並且您必須在其周圍添加未選中的{}以供編譯),但您似乎是正確的。我確信.NET會拋出一個錯誤,但它不會。 – userx 2009-11-10 20:53:47

+0

很少有研究表明,只要在這裏使用「unchecked」,這種方法就可以工作: http://msdn.microsoft.com/en-我們/圖書館/ khy08726%28VS.80%29.aspx – userx 2009-11-10 21:00:56

+0

啊是的 - 我忘了未經檢查。我似乎記得,對於發佈版本而言,默認情況是不會被選中的 - 儘管如果編譯器可以告訴某些東西會溢出(就像我的例子!! doh!),那麼它會阻止你。 – Ant 2009-11-11 09:28:15

0

在添加之前,將IntPtr轉換爲uint,然後應用偏移量。這會正常工作,但結果是long

據我所知,ulong和int是不可能的,所以64位指針部分是不正確的。事實上,它甚至沒有編譯。我真的不能想到一個優雅的解決方案,但只是使用long而不是安全。這是你可以使用的內存的一半*,8 exabytes :)儘管如此,內存地址映射在理論上可能是一個問題。

*:好,如果當前的.NET Framework實現不會從之前當然:)的這樣阻止你

1

.NET 4.0增加了一個新的靜態方法IntPtr.Add(IntPtr指針,int偏移量)。

在較早的.NET版本中,轉換爲整數的另一種方法是使用「不安全」代碼塊並將IntPtr強制轉換爲(byte *)。執行您的添加並將結果返回到IntPtr。編譯器負責指針寬度的細節。 :-)

例子:

new IntPtr((byte *)pipe.Root + EventNameOffset) 

或:

(IntPtr)((byte *)pipe.Root + EventNameOffset)