gpt4 book ai didi

c# - 如何获取指向托管类的原始内存指针?

转载 作者:太空狗 更新时间:2023-10-30 00:30:43 26 4
gpt4 key购买 nike

如何在 C# 中找到指向 托管 类的原始指针,并且希望它是内存中的原始大小?显然,这是 CLR 不允许的——更准确地说,是严格禁止的,因为出于稳定性和安全的原因,永远不应该使用托管类的非托管表示——所以我正在寻找 hack。我不是在寻找序列化 - 我确实需要托管类的转储,因为它在原始内存中表示。

更准确地说,我正在寻找类似以下示例中的函数 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!
*/

然而,我现在有点不知所措。根据this文章中,类中的前2个地址应该是指向SyncBlock和RTTI结构的指针,因此第一个字段的地址必须从头开始偏移2个字[32位系统中8字节,64位系统中16字节]。我的是 64 位;然而,正如您在输出中看到的那样,很明显第一个字段相对于对象地址的原始偏移量只有 4 个字节,这没有任何意义。

我已经问过这个 separate question .也许我应该将此作为一个单独的问题提出,但我的解决方案中可能存在错误。

最佳答案

嘿,这是你想要的吗?:

GCHandle gcHandle = GCHandle.Alloc(yourObject,GCHandleType.WeakTrackResurrection);
IntPtr thePointer = GCHandle.ToIntPtr(gcHandle);

关于c# - 如何获取指向托管类的原始内存指针?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33802676/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com