如何获得原始内存指针托管类? [英] How to get a raw memory pointer to a managed class?
问题描述
我要如何找到一个原始指针的管理的类在C#中,并希望它在内存中的原始大小?显然,这不是由CLR允许的 - 更准确地说,是严格禁止的,因为托管类的非托管表示应该永远永远也不能为稳定性和安全工作的原因 - 所以我在寻找一个黑客。我不是在寻找序列化 - 我的确需要管理类的垃圾,因为它是在原始内存代表
How do I find a raw pointer to a managed class in C#, and, hopefully, it's raw size in memory? Obviously, this is not allowed by CLR - more precisely, strictly prohibited, as unmanaged representation of managed classes should never, ever be worked with for both stability and safe reasons - so I'm looking for a hack. I'm not looking for serializing - I do actually need a dump of managed class as it is represented in raw memory.
更确切地说,我寻找类似功能 getObjectPtr
下面的例子:
More precisely, I'm looking for something like function getObjectPtr
in the following example:
IntPtr getObjectPtr(Object managedClass) {...}
void main() {
var test=new TestClass();
IntPtr* ptr_to_test=getObjectPtr(test);
Console.WriteLine(ptr_to_test.ToString());
}
在此先感谢!
Thanks in advance!
编辑:
我终于找到了解决我自己,而且,回来的时候发布它作为一个答案,是由量完全惊讶如此迅速地已经发布答案...感谢你们所有的人!这是非常快速和完全意想不到的。
I've finally found a solution by myself, and, when came back to post it as an answer, was totally surprised by the amount of so-quickly already posted answers... Thanks to all of you! This was very quick and totally unexpected.
最近的矿液是@ thehennyy的之一,但由于@Chino提出远远更好的我不张贴(抱歉,我'已经误认为这是错误的,首先,我刚刚忘了取消引用指针再次)。它不需要代码是不安全的,多一点容忍GC:
The closest to mine solution was @thehennyy's one, but I'm not posting it since @Chino proposed far better one (sorry I've mistaken it to be wrong at first, I've just forgot to dereference the pointer again). It does not require a code to be unsafe and a bit more tolerates 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,现在我是一个有点无能。按照这文章在类第一2地址应该是指针的SyncBlock和RTTI结构,因此,在第一场的地址必须由从头2字[在32位系统8字节,在64位的系统16字节]来抵消。我的是64位;然而,正如你可以在输出中看到的,很明显,第一场的原料从对象的地址偏移量只有4个字节,这没有任何意义。
Hovewer, now I'm a bit clueless. According to the this article, first 2 addresses in the class should be pointers to SyncBlock and RTTI structure, and therefore the first field's address must be offset by 2 words [8 bytes in 32-bit systems, 16 bytes in 64-bit systems] from the beginning. Mine is 64-bit; however, as you can see in the output, it is obvious that first field's raw offset from the object's address is only 4 bytes, which doesn't make any sense.
我问这是一个的另外一个问题。
也许我应该问这个作为一个单独的问题,但它可能是有我的解决方案错误。
推荐答案
嘿这是你想要什么:
GCHandle gcHandle = GCHandle.Alloc(yourObject,GCHandleType.WeakTrackResurrection);
IntPtr thePointer = GCHandle.ToIntPtr(gcHandle);
这篇关于如何获得原始内存指针托管类?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!