如何在C#中找到指向託管的類的原始指針,並且希望它在內存中的原始大小?顯然,這是CLR所不允許的 - 更準確地說,嚴格禁止,因爲託管類的非託管表示永遠不應該出於穩定和安全的原因 - 所以我正在尋找黑客。我不在尋找序列化 - 我實際上需要一個託管類的轉儲,因爲它在原始內存中表示。如何獲取原始內存指針到託管類?
更確切地說,我在下面的例子中尋找類似功能getObjectPtr
:
IntPtr getObjectPtr(Object managedClass) {...}
void main() {
var test=new TestClass();
IntPtr* ptr_to_test=getObjectPtr(test);
Console.WriteLine(ptr_to_test.ToString());
}
提前感謝!
編輯: 我終於找到了解決辦法我自己,而且,回來的時候將它張貼作爲一個答案,是由的所謂快速量完全驚訝已經張貼的答案...感謝所有你的!這非常快,而且完全出乎意料。
最接近我的解決方案是@ thehennyy的一個,但我沒有發佈它,因爲@Chino提出了更好的一個(抱歉,我錯誤地認爲它是錯誤的,我忘記解除引用指針再次)。它不需要代碼是不安全的,多一點容忍GC:
class Program
{
// Here is the function in case anyone needs it.
// Note, though, it does not preserve the handle while you work with
// pointer, so it is less reliable than the code in Main():
static IntPtr getPointerToObject(Object unmanagedObject)
{
GCHandle gcHandle = GCHandle.Alloc(unmanagedObject, GCHandleType.WeakTrackResurrection);
IntPtr thePointer = Marshal.ReadIntPtr(GCHandle.ToIntPtr(gcHandle));
gcHandle.Free();
return thePointer;
}
class TestClass
{
uint a = 0xDEADBEEF;
}
static void Main(string[] args)
{
byte[] cls = new byte[16];
var test = new TestClass();
GCHandle gcHandle = GCHandle.Alloc(test, GCHandleType.WeakTrackResurrection);
IntPtr thePointer = Marshal.ReadIntPtr(GCHandle.ToIntPtr(gcHandle));
Marshal.Copy(thePointer, cls, 0, 16); //Dump first 16 bytes...
Console.WriteLine(BitConverter.ToString(BitConverter.GetBytes(thePointer.ToInt32())));
Console.WriteLine(BitConverter.ToString(cls));
Console.ReadLine();
gcHandle.Free();
}
}
/* Example output (yours should be different):
40-23-CA-02
4C-38-04-01-EF-BE-AD-DE-00-00-00-80-B4-21-50-73
That field's value is "EF-BE-AD-DE", 0xDEADBEEF as it is stored in memory. Yay, we found it!
*/
Hovewer,現在我是一個有點無能。根據this文章,類中的前2個地址應該是指向SyncBlock和RTTI結構的指針,因此第一個字段的地址必須偏移2個字[32位系統中的8個字節,64位系統中的16個字節]從一開始就。我的是64位;但是,正如您在輸出中看到的那樣,顯然第一個字段的對象地址的原始偏移量僅爲4個字節,這沒有任何意義。
我已經問這個作爲separate question。 也許我應該問這是一個單獨的問題,但有可能是我的解決方案有錯誤。
簡短聲明:我通過google搜索找到任何東西,因爲搜索結果通常是指像「C++指針」和「教程C#不安全傻瓜」,我我沒有在自己的C#中找到合適的方法(包括查看元帥課程)。我很確定這個問題以前應該已經問過了,但是對於「原始C#指針」,「C#指向類的指針」,「指向類內存的原始指針」和「原始指向託管類的指針」,SO沒有得到任何結果。 – DeFazer
一般來說,你不能這樣做,因爲在你的傾銷中間GC可以將你的對象移動到其他位置。 –
也許,你可以使用'var h = GCHandle.Alloc(obj); var address =(IntPtr)h;'。 –