如果我在两台不同的计算机上从虚拟机运行程序,内存地址会相同吗?

3

对于C语言比较新,我学到地址取决于操作系统和CPU等因素。我在一门C课程的实验中被要求运行一个程序,并打印每个变量的地址,问我们这些地址和变量值是否与另一个同学(完全相同的程序)的相同。它们是本地变量,存储在堆栈上。通常我会说不可能,但是我们所有人都需要通过ssh连接到我们大学的实验室,我们的程序在相同规格的机器上运行。这就让我感到困惑了,我很确定这些值将是相同的,但我不知道确切是什么决定了这些地址。这是程序的一部分代码:

int g2(int a, int b)
{
 int c = g1(a + 3, b - 11);
 printf("g2: %d %d %d \n", a,b,c);
 printf("a's address is %p b's address is %p C's address is %p\n", &a, &b, &c);
 return c - b;
}

对我来说,a的地址是0x7ffe9bce4a0c。我并不是在寻找作业答案,而是问这里,因为我的队友们没有发送他们的地址,我们被允许这样做。我已经进行了调查,但找不到与这种情况相匹配的答案,非常感谢您的帮助,谢谢!


7
即使您在自己的计算机上运行同一个程序两次,地址也不保证相同... - Stephan Lechner
哦,好的,我不知道这个,谢谢! - Jackson
2
这可能只是巧合,但这取决于不仅仅是操作系统和CPU。例如,C编译器在调用main()之前可能会使用更多或更少的堆栈空间 -- 这可能取决于版本或其他因素。 - Lou Franco
1
https://en.wikipedia.org/wiki/Address_space_layout_randomization - Hans Passant
非常感谢大家的解释,我之前不知道ASLR,但在自己的机器上运行了几次后发现了不同的地址。谢谢! - Jackson
1
为了符合标准,当使用"%p"打印时,请将地址转换为void*,例如:printf("a的地址是 %p\n", (void*)&a); - pmg
3个回答

4

"如果我在两台不同的计算机上从虚拟机运行程序,内存地址会相同吗?"

不会,即使在同一环境和同一台机器上运行,它们也很可能不相同。没有任何保证它将具有相同的地址。

现代操作系统会随意分配内存(当然是在某些部分内),这是有好原因的:防止黑客利用内存漏洞对程序甚至操作系统造成伤害。

这种技术被称为地址空间布局随机化。您可以在这里了解更多信息。


可能在多次执行中,变量可能具有相同的地址,但不能保证下一次运行会再次发生。实际上,如果操作系统支持ASLR,则更有可能出现“几乎保证”地址不相等的情况。
虚拟机对此行为没有影响。如果您的特定虚拟机支持ASLR,请阅读更多关于内存存储的文档,但应遵循相同的指南。

2

简短回答,不行。

  1. 操作系统每次加载程序时,都会在不同的位置。
  2. 你看到的地址并不是内存中的实际地址。有一个抽象的地址层,由操作系统提供。如果你想了解更多关于虚拟内存地址的知识,可以学习操作系统课程。

2
无论您得到相同的地址还是不同的地址,这取决于操作系统。
不久前,如果程序打印其函数中一个本地变量的地址,则只要在程序执行的同一点以相同的程序输入和其他情况下调用该函数,那么该地址每次运行程序时都将保持不变。 (哪些函数被调用,包括递归调用,以及它们使用多少堆栈空间可能会受到程序输入和其他因素的影响。)这是因为当程序加载和初始化时,其堆栈始终从相同的内存地址开始。
恶意人士利用了这种行为——如果程序中存在漏洞,它们可能会被利用,并且知道程序中使用的地址有助于某些攻击。因此,常见的操作系统已经改变了这种行为。现在,当启动程序时,其堆栈位置和其他部分的内存布局位置会随机调整。这称为地址空间布局随机化(ASLR)。
因此,在常见的现代操作系统中,每次打印本地变量的地址时都会得到不同的地址。在专用操作系统(例如嵌入式设备的操作系统)中,您可能每次都会得到相同的地址。
您的问题标题询问“VM”,大概是指虚拟机,但在问题正文中没有提到。只要虚拟机正确实现了机器,它应该产生相同的行为。因此,无论程序是否在虚拟机中运行,都不应与此问题有关。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接