12

我对程序在内存中的样子有点困惑,我的教授告诉我堆栈和堆相互增长,堆栈位于较低的内存地址。

该图像困扰我的第一件事是,如果堆从高到低增长,那么如果我在堆上分配了一个数组,那么指向第二个元素的指针的 int 值是否应该小于指向第一个元素的指针?这会令人困惑

我做了一些研究,发现了这个数字(注意我的问题集中在 linux 上)

布局
(来源:cyberplusindia.com

好的,所以数据和未初始化的数据出现在文本段之后,位于程序内存的开头,然后是堆,然后是堆栈,最后是命令行参数和环境。

但是如果堆栈从高地址增长到低地址,那么如果我在堆栈上分配了一个数组,那么指向第一个元素的指针的值也会低于指向第二个元素的指针的值吗?这是否意味着堆栈也会从低到高增长?

所以我的问题是 Linux 中进程的正确内存布局是什么?以及共享库的内存来自哪里(在进程的地址空间中)

带有指针示例的简单代码:

#include <iostream>


int data[5];

int main()
{
  using std::cout;
  using std::endl;
  int stack = 0;
  short *sptr = reinterpret_cast<short *> ( &stack );
  int *iptr = new int[5];
  cout << "Starting static tests"
       << "\nPointer to first element " << data
       << "\nPointer to second element " << &data[1]
       << "\nstarting stack test " <<  sptr
       << "\nsecond short " << &sptr[1]
       << "\nStarting heap test " << iptr
       << "\nsecond int " << &iptr[1];
  delete[] iptr;
  return 0;
}

输出:

Starting static tests
Pointer to first element 0x6013e0
Pointer to second element 0x6013e4
starting stack test 0x7fffdf864dbc
second short 0x7fffdf864dbe
Starting heap test 0x1829010
second int 0x1829014
4

2 回答 2

3

如果我在堆栈上分配了一个数组,那么指向第一个元素的指针的值也会低于指向第二个元素的指针?

“如何”分配数组并不重要,您可以增加或减少堆栈指针,但结果是您为数组保留了地址空间。

您可以以正常方式使用它们,因为最低地址是为元素 0 保留的。

所以我的问题是 Linux 中进程的正确内存布局是什么?

你可以自己检查。在您的程序中插入某个地方,例如std::cin.get()暂停您的程序。

然后在单独的 shell 中运行:

ps aux | grep your_program_name
cat /proc/<pid show by grep>/maps 

这将打印您的进程的内存映射,您可以在其中看到堆、堆栈和其他东西在内存中的放置位置。

关于堆栈:假设您有一台普通机器,装有 Linux 和 Intel 或 AMD 64 位 CPU。然后编写以下代码:

extern void f(int);

void g(int param)
{
    f(param);
}

编译并反汇编:

g++ -ggdb -c test_my_stack.cc  && objdump -S test_my_stack.o

你可以看到(删除了不重要的细节):

 void g(int param)
 {
 0:   55                      push   %rbp
 1:   48 89 e5                mov    %rsp,%rbp
 4:   48 83 ec 10             sub    $0x10,%rsp
 8:   89 7d fc                mov    %edi,-0x4(%rbp)
    f(param);
 b:   8b 45 fc                mov    -0x4(%rbp),%eax

正如您在sub $0x10,%rsp我们通过减少(向下移动)堆栈指针来保留堆栈中的空间中看到的那样。

于 2013-07-14T00:51:56.420 回答
3

该图像困扰我的第一件事是,如果堆从高到低增长,那么如果我在堆上分配了一个数组,那么指向第二个元素的指针的 int 值是否应该小于指向第一个元素的指针?这会令人困惑

一点也不。假设您从一个从高到低增长的内存池中分配了一个 10 字节的数组。分配器所要做的就是将该内存池的“底部”减 10,然后将该值用作分配数组的开始。然后数组将在旧的“底部”结束。指针算术仍然可以按预期工作,但您会“成长”到低地址。

于 2013-07-14T00:58:15.767 回答