gpt4 book ai didi

c# - 有什么工具可以在.NET 程序执行时查看变量的存储位置?是在栈上还是堆上?

转载 作者:IT王子 更新时间:2023-10-29 04:22:51 25 4
gpt4 key购买 nike

很久以前,我想知道变量(无论是值类型还是引用类型)的确切存储位置。它会在堆栈上还是堆上?

我已阅读 Eric Lippert’s article一样的。

出于好奇,我想要的是交叉验证我所理解的相同内容。是否存在相同的工具?或者我会以任何方式知道,当 .NET 程序正在执行时,哪些变量会存储在堆栈中?哪个存储在堆上?

谢谢

最佳答案

将存储按堆栈和堆划分的想法是一种方便的抽象,可以很好地为您服务。但更复杂的是,.NET 程序中有 6 个不同的变量存储位置。

这里选择的工具是调试器,它可以准确显示变量的存储位置。这确实需要深入了解机器代码的工作原理。使用 Debug + Windows + Disassembly 查看机器码。查看程序的发布版本并更改设置,即使在调试时也能优化代码,这一点也很重要。工具 + 选项、调试、常规,取消勾选“模块加载时抑制 JIT 优化”选项。您现在将看到机器代码将在您的用户机器上执行的方式。

你必须事先知道的事情才能理解这一切:

  • 引用类型的对象存储在 GC 堆上。存储引用的变量与值类型值具有相同类型的存储选择。
  • 值类型值或对象引用有六个可能的存储位置:
  • 如果变量是引用类型
  • 的成员,则它们存储在 GC 堆上。
  • 如果变量声明为静态
  • ,它们将存储在 AppDomain 的加载程序堆中。
  • 如果变量为 [ThreadStatic]
  • ,则它们存储在线程本地存储中
  • 如果变量是方法参数或局部变量
  • ,它们可以存储在堆栈帧中。
  • 如果变量是方法参数或局部变量,它们可以存储在 CPU 寄存器中
  • 特定于 x86 抖动,Single 或 Double 类型的变量可以存储在 FPU 堆栈中。

  • 后三个要点是它变得复杂的地方,以及为什么您需要查看机器代码以找出它们的存储位置。它是高度特定于实现的,抖动的类型很重要。并且受您是否启用抖动优化器的影响很大。在这里做出正确的选择对于性能非常重要。粗略的轮廓(跳过ARM抖动):
  • 前两个方法参数存储在 x86 抖动的 CPU 寄存器中,包括实例方法的 this 值。 x64 抖动使用 4 个寄存器。浮点处理器寄存器用于传递 x86 上的 Single 和 Double 类型的变量,x64 上的 XMM 寄存器
  • 函数返回值在 CPU 寄存器中返回,如果合适,使用 EAX 或 RAX 寄存器,如果它是浮点值,则使用 ST0。如果它不适合,则调用者在堆栈帧上为该值保留空间并将指针传递给它
  • 抖动优化器寻找机会在 CPU 寄存器中存储局部变量。如果因为寄存器用完而被迫这样做,它可能会将寄存器溢出回堆栈帧。

  • 这些实现细节有许多可观察到的副作用:
  • 获取存储在 cpu 寄存器中的局部变量会使代码难以调试。调试器对存储位置的了解不够。这是 Debug 版本存在的主要原因,它抑制了优化,因此您可以轻松检查局部变量,调试器确实知道用于变量
  • 的堆栈帧槽。
  • 您无法检查方法的返回值,这在调试时会带来很大的不便。调试器对抖动选择的存储位置的了解不足以可靠地找到该值。编辑:在 VS2013 中修复
  • 由于变量被优化为存储在 cpu 寄存器中,因此您可能难以调试线程问题。在循环或 if() 语句中测试值会产生寄存器中值的副本,而不是存储在内存中的值。特别是 x86 抖动问题和 volatile 关键字的原因,该关键字抑制了此优化
  • 您可以初始化指向局部变量的指针,而无需固定它。与存储在 GC 堆中的变量可能会被垃圾回收移动并因此需要固定不同,局部变量具有固定的存储地址,该地址在整个方法体
  • 中均有效。
  • 为堆栈帧分配的空间量由抖动决定。但是可以自己分配一个块,C# stackalloc 关键字支持它。这是您可以直接分配的最快内存
  • 将浮点值存储在 FPU 寄存器中会导致浮点精度问题。当它存储在 FPU 中时,值以 80 位精度存储。但是当它溢出到内存时,它会被截断为 32 或 64 位精度。这种溢出何时发生的不可预测性(加上 x64 抖动的不同策略)会产生不同的浮点结果,如果计算丢失了很多有效数字,则微小的变化会导致计算结果的巨大差异。
  • 关于c# - 有什么工具可以在.NET 程序执行时查看变量的存储位置?是在栈上还是堆上?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14022680/

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