【发布时间】:2021-02-08 08:14:27
【问题描述】:
每当我们需要找到变量的地址时,我们在 C 中使用下面的语法,它会打印变量的地址。我想了解的是返回的地址是实际的物理内存位置或编译器抛出一些随机数。如果它是物理的或随机的,它是从哪里获得这些数字的,或者它必须存储在内存中的哪里。内存位置的地址实际上在内存中占用空间吗?
int a = 10;
printf("ADDRESS:%d",&a);
地址:2234xxxxxxxx
【问题讨论】:
每当我们需要找到变量的地址时,我们在 C 中使用下面的语法,它会打印变量的地址。我想了解的是返回的地址是实际的物理内存位置或编译器抛出一些随机数。如果它是物理的或随机的,它是从哪里获得这些数字的,或者它必须存储在内存中的哪里。内存位置的地址实际上在内存中占用空间吗?
int a = 10;
printf("ADDRESS:%d",&a);
地址:2234xxxxxxxx
【问题讨论】:
此位置来自分配给您的程序的virtual address space。换句话说,这是来自virtual memory,您的操作系统会在需要时将其映射到物理内存。
【讨论】:
这取决于您拥有的系统类型。
微控制器应用等低端系统通常只支持物理地址。
中档 CPU 通常带有一个 MMU(内存映射单元),它允许将所谓的虚拟内存放置在物理内存之上。这意味着代码的某个部分可以从地址 0 工作到 x,尽管实际上这些虚拟地址只是物理地址的别名。
PC 等高端系统通常只允许访问虚拟内存,而拒绝应用程序直接访问物理内存。他们还经常使用Address space layout randomization (ASLR) 为某些类型的内存生成随机地址布局,以防止利用硬编码地址的黑客攻击。
在任何一种情况下,实际地址本身都不会占用内存空间。
更高的抽象层概念(例如文件系统)可能会在查找表等中存储地址,然后它们会占用内存。
【讨论】:
…返回的地址是实际物理内存位置或编译器抛出一个随机数
在通用操作系统中,C 程序中的地址是虚拟内存地址。1
如果它是物理的或随机的,它是从哪里得到这些数字的,或者它必须存储在内存中的哪里。
将您的程序加载到内存中的软件会最终决定使用哪些地址2,它可能会以各种方式通知您的程序这些地址,包括:
因此,当您的程序想要评估 &x 时,它可能会从它所在部分的开头获取 x 的偏移量(并且该偏移量由编译器内置到程序中,并且可能由链接器)并将其添加到该部分的基地址。结果总和是x的地址。
内存位置的地址实际上占用内存空间吗?
C 标准不要求程序为x、&x 的地址使用任何内存。 &x 的结果是一个值,就像3*x 的结果一样。编译器对一个值唯一要做的就是确保它被用于它所使用的任何进一步的表达式。不需要将它存储在内存中。但是,如果程序在一段代码中处理许多值,那么没有足够的处理器寄存器来保存它们,编译器可能会选择将值临时存储在内存中。
1 虚拟内存是一个概念或“想象的”地址空间。您的程序可以使用虚拟地址执行,因为硬件在执行程序时会自动将虚拟地址转换为物理地址。操作系统创建一个映射,告诉硬件如何将虚拟地址转换为物理地址。 (该映射还可能告诉硬件某些虚拟内存目前实际上不在物理内存中。在这种情况下,硬件会中断程序并启动处理该问题的操作系统例程。该例程将所需的数据安排到被加载到内存中,然后更新虚拟内存映射以表明这一点。)
2 程序的各个部分在内存中的布局通常有一个通用的方案,例如在一个区域启动指令,在另一个区域为堆栈设置空间。在现代系统中,一些随机性被有意添加到地址中,以阻止恶意人员试图利用程序中的错误。
【讨论】: