2

在我对后台发生的事情进行实验后,我对堆栈内存组织非常好奇,并且显然看到它与我从书本上获得的微小知识相匹配。只是想检查一下我的理解是否正确。

我有一个基本程序——有 2 个函数,第一个是 foo,另一个是 main(入口点)。

void foo(){
    // do something here or dont
}

int main(){

    int i = 0;

    printf("%p %p %p\n",foo, &i, main);

    system("PAUSE");
    return EXIT_SUCCESS;
};

程序的输出如下图所示,main 的局部变量 i 完全位于不相关的位置。integer 是一种值类型,但使用 char * 本地指针再次检查它并获得类似的结果。

00401390 0022FF44 00401396
Press any key to continue . . .

我主要了解代码和变量被分配到不同的内存段(代码段/数据段)。所以基本上可以说调用堆栈折叠有关函数执行的基本信息(它们的局部变量、参数、返回点)并将它们保存在数据段中吗?

4

5 回答 5

3

一开始有一点警告:所有这些答案都受到操作系统和硬件架构的影响。Windows 所做的事情与类 UNIX 语言、实时操作系统和旧的小型系统 UNIX 完全不同。

但正如@Richie 和@Paul 所说,基本答案是“是的”。当您的编译器和链接器处理完代码时,它在 UNIX 中被分解为所谓的“文本”和“数据”段。一个文本段包含指令和一些静态数据;数据段包含数据。

然后为堆栈和堆空间分配一大块数据段。其他块可以分配给静态或外部数据结构之类的东西。

所以是的,当程序运行时,程序计数器正忙于从与数据不同的段中获取指令。现在我们进入一些架构依赖关系,但一般来说,如果你有分段内存,你的指令的构造方式是从段中获取一个字节尽可能高效,在旧的 360 架构中,它们有基址寄存器,在 x86随着地址空间从旧的 8080 到现代处理器,有一堆头发变长了,但是所有指令都经过非常仔细的优化,因为正如您可以想象的那样,获取指令及其操作数的使用非常密集。

现在我们使用虚拟内存和内存管理单元来了解更现代的架构。现在机器有了特定的硬件,让程序将地址空间视为一个大的平坦地址范围;各个段只需放置在该位虚拟地址空间中。MMU 的工作是获取一个虚拟地址并将其转换为一个物理地址,包括如果该虚拟地址目前根本不在物理内存中该怎么办。同样,MMU 硬件经过高度优化,但这并不意味着没有相关的性能成本。但是随着处理器变得越来越快,程序越来越大,它变得越来越不重要。

于 2009-04-29T15:39:49.980 回答
1

是的,完全正确。代码和数据存在于内存的不同部分,具有不同的权限。堆栈保存参数、返回地址和本地(“自动”)变量,并与数据一起存在。

于 2009-04-29T14:38:39.423 回答
0

是的。

想象一下,你的代码存储器是 ROM,而你的数据存储器是 RAM(一种常见的小芯片架构)。然后你看到堆栈必须在数据存储器中。

于 2009-04-29T14:47:23.273 回答
0

您的程序表现出未定义的行为,具体是因为:

  • 您没有包含<stdio.h><cstdio>取决于您将代码编译为的语言
  • printf并且所有可变参数函数都没有能力对其参数进行类型检查。因此,您必须传递正确键入的参数。你真的应该这样做:
  • system()范围内没有声明。包括<stdlib.h><cstdlib>视情况而定。

将您的代码编写为:

   #include <stdio.h>

   int main() {
      /* ... */
      printf("%p %p %p\n", (void *)foo, (void *)&i, (void *)main);
      /* ... */
   }

另请注意:

  • 的定义void foo()不是 C 中的原型,而是 C++ 中的。但是,如果您要编写void foo(void) ,您将获得两种语言的原型。
  • system()是依赖于实现的——你的代码在不同平台上的行为可能不符合预期。

语言本身(C 或 C++)对如何组织内存没有任何限制。它甚至没有堆栈或堆的概念。这些是由它们认为合适的实现定义的。理想情况下,您应该查阅实现提供的文档,以公平地了解它们的作用。

于 2009-04-29T15:44:32.263 回答
0

好吧,我可以代表 SPARC:

是的。运行程序时,程序会被读取两次(至少在 SPARC 中)。程序被加载到内存中,然后任何数组/堆栈分配都会被加载。在程序的第二遍中,堆栈被分配到单独的内存中。

我不确定基于 CISC 的处理器,但我怀疑它变化不大。

于 2009-04-29T15:46:33.020 回答