在菜鸟教程上学习C#结构体这一节时(https://www.runoob.com/csharp/csharp-struct.html),里面提到了一个关于结构体性能和内存分配的问题:“结构体是值类型且在栈上分配内存;而类是引用类型,可能涉及更多的内存开销和管理。”于是在vs2022环境下对代码进行了反汇编。
using System;/*原代码*/namespace HelloWorld
{class Program{struct Struct{public string str;}class Class{public string str = new string("Where there is a will, there is a way !");}static void Main(string[] args){Struct s1 = new Struct();s1.str = "Hello, World!";Struct s2 = s1;Class c1 = new Class();}}
}
# 反汇编代码static void Main(string[] args){
088F3EF8 push ebp
088F3EF9 mov ebp,esp
088F3EFB push edi
088F3EFC push esi
088F3EFD push ebx
088F3EFE sub esp,3Ch
088F3F01 vxorps xmm4,xmm4,xmm4
088F3F05 vmovdqu xmmword ptr [ebp-48h],xmm4
088F3F0A vmovdqu xmmword ptr [ebp-38h],xmm4
088F3F0F vmovdqu xmmword ptr [ebp-28h],xmm4
088F3F14 xor eax,eax
088F3F16 mov dword ptr [ebp-18h],eax
088F3F19 mov dword ptr [ebp-14h],eax
088F3F1C mov dword ptr [ebp-38h],ecx
088F3F1F cmp dword ptr ds:[898A788h],0
088F3F26 je HelloWorld.Program.Main(System.String[])+035h (088F3F2Dh)
088F3F28 call 542824F0
088F3F2D nop Struct s1 = new Struct();
088F3F2E xor ecx,ecx
088F3F30 mov dword ptr [ebp-3Ch],ecx s1.str = "Hello, World!";
088F3F33 mov dword ptr [ebp-3Ch],8B5623Ch Struct s2 = s1;
088F3F3A mov ecx,dword ptr [ebp-3Ch]
088F3F3D mov dword ptr [ebp-40h],ecx Class c1 = new Class();
088F3F40 mov ecx,0AEEDC9Ch
088F3F45 call CORINFO_HELP_NEWSFAST (051E300Ch) # 有关内存分配的一个函数(Copilot AI解释)
088F3F4A mov dword ptr [ebp-48h],eax
088F3F4D mov ecx,dword ptr [ebp-48h]
088F3F50 call HelloWorld.Program+Class..ctor() (0AF09AD0h) # 构造函数(Copilpt AI解释)
088F3F55 mov eax,dword ptr [ebp-48h]
088F3F58 mov dword ptr [ebp-44h],eax }
由于C#代码运行在.net运行时环境上(类似于jvm虚拟机环境),所以无法直接查看进程的实际内存情况。可以看到结构体对象分配在栈上,并且可以得出dword ptr [ebp-3Ch]
与dword ptr [ebp-40h]
均为指针,其中8B5623Ch
为字符串常量的地址,而类对象则分配在堆上,dword ptr [ebp-44h]
为类对象的地址。