CLR -存储引用地址的地方

本文关键字:地址 引用 存储 CLR | 更新日期: 2023-09-27 18:12:42

我是一个编程新手,这给我带来了很多困惑。

假设我们有以下语句:

Int32 i = 1;

i的内容存储在内存中,内存为4个字节:00000000 00000000 00000000 00000001

CLR以后如何访问这个内存位置?CLR是否将地址存储到这个内存块的某个地方?

CLR -存储引用地址的地方

System.Int32是一个值类型,没有引用。

事实上,如果编译器能找到一个CPU寄存器在局部变量的整个生命周期中保存它,那么局部变量可能永远不会在内存中。

如果它在内存中,它的地址将通过在堆栈指针(ESP)或包含它的引用类型(c#中的class)对象的地址上添加偏移量来找到。

在JIT生成的代码中,值类型的变量与本机代码使用的变量是无法区分的(没有对象头或类似的东西)。

编译器跟踪变量的位置,以便它可以创建以正确方式访问它的代码。

在这种情况下,你声明了一个局部变量,所以它将在堆栈上分配。

程序不会访问特定地址的变量,而是作为基指针的偏移量访问,基指针指向当前方法的堆栈帧。

例如,将变量设置为1的代码在编译为32位应用程序的机器码时看起来像这样:
mov dword ptr [ebp-8],1

ebp寄存器指向堆栈帧的顶部,因此在本例中i变量被分配到比它低8个字节的位置。

假设正常情况下,如果i是一个局部变量,它将被保存在堆栈上。. net的抽象虚拟机是基于堆栈的虚拟机。

我要补充的是,在英特尔/AMD i不会这样保存:-)英特尔/AMD是小尾端。所以改成00000001 00000000 00000000 00000000

我把它混合了一点…现在…IL语言和。net 抽象 VM是"纯"基于堆栈的,所以有一个堆栈:-)(但没有寄存器,所以"纯")(我希望你知道堆栈是什么)。当代码被编译为您正在使用的计算机的机器码时,i可能会被放入寄存器或堆栈中。

注意一般来说说值类型(或者非引用类型,如果你想包含托管/非托管指针/引用)保存在堆栈和/或寄存器中是错误的。他们被拯救在他们被拯救的地方。例如,类的值类型成员被保存在类中(因此通常在堆中)。yield函数、异步函数、"普通"方法中的值类型,但被"闭包类型"匿名函数引用时,通常保存在堆的某个地方。但是这些都是参考实现细节

据我所知,实际的堆分配引用被存储为双指针(或一些等效的),以便垃圾收集器可以移动内存,而不必通过更新指向的指针来影响代码中引用的任何地方。