Ran*_*tha 25 .net c# vb.net memory-management
从很久以前我想知道确切地存储变量(值类型或引用类型)的位置.它会在堆栈还是堆上?
我也读过Eric Lippert的文章.
出于好奇,我想要的是交叉验证我所理解的内容.任何工具都存在相同的?或者以任何方式我会知道,当.NET程序被执行时,哪些变量存储在堆栈中?哪个存储在堆上?
谢谢
Han*_*ant 69
考虑存储被堆栈和堆分割是一种方便的抽象,可以很好地为您服务.但它更复杂,.NET程序中的变量有6个不同的存储位置.
这里选择的工具是调试器,它可以准确显示变量存储的位置.这需要深入了解机器代码的工作原理.使用Debug + Windows + Disassembly查看机器代码.查看程序的Release版本并更改允许代码优化的设置也很重要,即使在调试时也是如此.工具+选项,调试,常规,取消选中"抑制模块加载时的JIT优化"选项.您现在将看到机器代码在用户机器上的执行方式.
你必须事先了解的事情才能理解这一切:
引用类型的对象存储在GC堆上.存储引用的变量与值类型值具有相同类型的存储选择.
值类型值或对象引用有六个可能的存储位置:
后三个子弹是它变得复杂的地方,为什么你需要查看机器代码来找出它们的存储位置.它具有高度的实现特性,抖动类型很重要.并且您是否已启用抖动优化器会对此产生很大影响.在这里做出正确的选择对于perf非常重要.粗略轮廓(跳过ARM抖动):
前两个方法参数存储在x86抖动的CPU寄存器中,包括此实例方法的值.x64抖动使用4个寄存器.浮点处理器寄存器用于在x86上传递Single和Double类型的变量,在x64上传递XMM寄存器
如果CPU寄存器适合,则使用EAX或RAX寄存器返回函数返回值,如果它是浮点值,则返回ST0.如果它不适合,那么调用者在堆栈帧上为值保留空间并传递指针
抖动优化器寻找在CPU寄存器中存储局部变量的机会.如果强制执行此操作,它可能会将寄存器溢出回堆栈帧,因为它已超出寄存器.
这些实现细节有许多可观察到的副作用: