可以说我有一个结构。我们还假装我们不知道它的类型。这就是为什么我们把它装箱而无法拆箱。
public struct Player{
public float hp;
public float maxHP;
}
var boxedPlayer = (object)new Player();
var typeSize = typeof(Player);
var ourAllocatedMemoryPTR = (byte*)someAllocCall();
// Copy the object into the new memory
var objHandle = GCHandle.Alloc(boxedPlayer , GCHandleType.Pinned);
var adress = objHandle.AddrOfPinnedObject();
var ptr = adress.ToPointer();
Buffer.MemoryCopy(ptr, ourAllocatedMemoryPTR, typeSize, typeSize);
objHandle.Free();
Run Code Online (Sandbox Code Playgroud)
据我所知,装箱结构...与结构本身的大小不同...因为它被装箱和管理。因此,头部或尾部有一些字节将其定义为一个对象,一个装箱结构。因此上面的示例将整个装箱结构复制到内存中。据我所知。这不是我们想要的。
是否可以仅将框内的结构复制到分配的内存中?我们新分配的内存应该只存储结构,而不是装箱的结构。我认为通过将结构从盒子中取出来可能可以吗?在复制过程中切割将其定义为盒子的部分或头部/尾部?
这可能吗 ?结构体到底是如何装箱的?前后添加了多少字节?记忆中的它是什么样的?
很高兴获得任何帮助!谢谢 :)
确切的内部布局可能会发生变化。GCHandle.AddrOfPinnedObject()等方法旨在为您提供指向对象数据的指针,而不是指向标头、方法表或填充字节等内部内容的指针。因此,只需使用这些方法即可,不要自己进行数学计算。
检索固定句柄中对象数据的地址。
强调我的
在撰写本文时(以及几年前),内存中的 .NET 对象具有以下布局:
您可以通过以下代码看到这一点。我对字段进行了一些简化,以便我们可以比使用float
.
public struct Player
{
public int hp ;
public int maxHP;
}
class Program
{
static unsafe void Main()
{
var player = new Player();
player.hp = 0xAABB;
player.maxHP = 0xCCDD;
var boxedPlayer = (object) player;
lock (boxedPlayer)
{
Console.ReadLine(); // Put a breakpoint here
}
}
}
Run Code Online (Sandbox Code Playgroud)
在 32 位中,内存布局(调试/Windows/内存)为:
64 位内存布局:
Player
)hp
此处maxHp
此处如果您现在继续
var ourAllocatedMemoryPTR = (byte*) Marshal.AllocHGlobal(1024);
var objHandle = GCHandle.Alloc(boxedPlayer, GCHandleType.Pinned);
var adress = objHandle.AddrOfPinnedObject();
var ptr = adress.ToPointer();
Buffer.MemoryCopy(ptr, ourAllocatedMemoryPTR, sizeof(Player), sizeof(Player));
Run Code Online (Sandbox Code Playgroud)
你会看到它ptr
指向 0x04a2a770,即 0x04ECA76C + 4(就在数据开始的地方)。sizeof(Player)
是8,是两个4字节的int
。
ourAllocatedMemoryPTR
之前和之后的记忆Buffer.MemoryCopy()
:
在像 WinDbg 这样的调试器中,您会得到以下 32 位结果:
0:009> dd 0486a76c-4 L4
0486a768 00000001 06d68ff8 0000aabb 0000ccdd
^Address ^Header ^MT ^hp ^maxHP
0:009> ? aabb
Evaluate expression: 43707 = 0000aabb
0:009> ? ccdd
Evaluate expression: 52445 = 0000ccdd
0:009> !do 0486a76c
Name: BoxedStructInMemory.Player
MethodTable: 06d68ff8
EEClass: 06d58ee4
Size: 16(0x10) bytes
File: C:\Users\...\BoxedStructInMemory.dll
Fields:
MT Field Offset Type VT Attr Value Name
0484697c 4000001 4 System.Int32 1 instance 43707 hp
0484697c 4000002 8 System.Int32 1 instance 52445 maxHP
ThinLock owner 1 (02810B18), Recursive 0
Run Code Online (Sandbox Code Playgroud)
对于 64 位:
0:009> dq 000001a3c93ead50-8 L3
000001a3`c93ead48 00000001`00000000 00007ff8`a2f22180
000001a3`c93ead58 0000ccdd`0000aabb
0:009> !do 000001a3c93ead50
Name: BoxedStructInMemory.Player
MethodTable: 00007ff8a2f22180
EEClass: 00007ff8a2f1c5e8
Size: 24(0x18) bytes
File: C:\Users\...\BoxedStructInMemory.dll
Fields:
MT Field Offset Type VT Attr Value Name
00007ff8a2e2b1f0 4000001 8 System.Int32 1 instance 43707 hp
00007ff8a2e2b1f0 4000002 c System.Int32 1 instance 52445 maxHP
ThinLock owner 1 (000001A3C7899930), Recursive 0
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
488 次 |
最近记录: |