关于C#:堆栈和堆内存的大小

Size of stack and heap memory

本问题已经有最佳答案,请猛点这里访问。

Possible Duplicate:
What and where are the stack and heap?

关于C程序内存布局的基本概念,我理解:

  • 该语言使用两个主要数据结构堆栈和堆。
  • 创建堆栈以存储子例程的局部变量和簿记数据。
  • 创建堆以存储程序的动态分配变量
  • 堆本质上是可变长度的。(在堆栈上不太确定)
  • 通常,编译器/语言负责在执行之前请求操作系统创建这些数据结构。

问题

  • 创建堆栈/堆的初始大小是多少?谁来决定?
  • 它们是在哪里产生的物理内存?我看到一个一般的描述,"栈是在顶层地址创建的,堆是在底层地址创建的",请对此进行详细说明。

"Stack is created in the top-level-address and the heap at the
low-level-address" Please elobarate this

这是一个神话。它可能有历史真相的基础。它有时会与你在现实生活中看到的东西产生共鸣。但事实并非如此。

不过,很容易探索:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdlib.h>
#include <stdio.h>

void check(int depth) {
    char c;
    char *ptr = malloc(1);
    printf("stack at %p, heap at %p
"
, &c, ptr);
    if (depth <= 0) return;
    check(depth-1);
}

int main() {
    check(10);
    return 0;
}

在我的机器上,我看到:

1
2
3
4
5
6
7
8
9
10
11
stack at 0x22ac3b, heap at 0x20010240
stack at 0x22ac0b, heap at 0x200485b0
stack at 0x22abdb, heap at 0x200485c0
stack at 0x22abab, heap at 0x200485d0
stack at 0x22ab7b, heap at 0x200485e0
stack at 0x22ab4b, heap at 0x200485f0
stack at 0x22ab1b, heap at 0x20048600
stack at 0x22aaeb, heap at 0x20048610
stack at 0x22aabb, heap at 0x20048620
stack at 0x22aa8b, heap at 0x20048630
stack at 0x22aa5b, heap at 0x20048640

所以,堆栈是向下的,堆是向上的(正如您根据神话所预期的那样),但是堆栈的地址较小,并且它们之间没有向对方增长(神话被破坏)。

顺便说一句,我的check函数是尾部递归的,在某些具有编译器选项的实现中,您可能会看到堆栈根本没有移动。这就告诉了你为什么标准没有规定所有这些是如何工作的——如果它这样做了,可能会无意中禁止有用的优化。


如前所述,大小是特定于操作系统的。例如,在使用Visual Studio的Windows上,默认堆栈大小为1MB

MSDN

在Linux上,下面的命令可以显示当前的命令。

1
ulimit -s or -a

在我的LinuxMint 64位上,它显示8192kb。

每个程序在装入内存时都有几个段。在程序集中,可以指示使用.data、.code等前缀(intelx86)的每个前缀。

它是数据段,有几个小节。除了其他几个堆栈之外,堆栈和堆都是它的一部分。

堆栈也可以隐式增长,即当您进行另一个函数调用时,激活记录被推到堆栈上,它们利用更多的堆栈内存。这就是当程序用完分配的堆栈时,无限递归导致崩溃的原因。

当函数调用返回时,将弹出该激活记录并缩小堆栈。

相反,堆从相反的方向增长,包含所有动态分配的内存。

这两个段反向增长的原因是为了最大限度地利用它们的组合内存。请注意,正如注释中所提到的,这不是C标准,但大多数常见的操作系统都实现了这一点。

------堆栈开始----------堆栈向下增长

——除非它们相互交叉,否则程序可以运行。

-------堆开始-----------堆向上增长

如果您的程序不使用堆,那么您的堆也可以使用最大内存,包括堆的内存。如果程序很少进行递归调用,并且使用最小的局部变量(即使用较少的内存进行堆栈),那么它可以最大限度地利用堆。

数据段的其他部分是BSS等,其中可能包含未初始化的静态变量等字段。


What is the initial size with which a stack/heap is created? and who decides it?

这是特定于编译器和操作系统的。

Wherein physical memory are they are created? I see a general description as"Heap is created in the top-level-address and stack at the low-level-address".

这是特定于编译器和操作系统的。

真正地。语言标准没有规定最小堆栈大小,也没有指定堆栈或堆在内存中的位置。这样做的原因是使C程序更少地依赖于这些细节,因此更易于移植到不同的平台(读:不同的操作系统、不同的CPU、不同的编译器)。


首先,C标准没有对堆栈/堆的实现方式施加任何要求。平台。

What is the initial size with which a stack/heap is created? and who decides it?

通常,操作系统为每个进程分配一个固定大小的堆栈,这是平台特定的。堆大小没有限制,程序通常拥有所有可用的虚拟地址空间。

Wherein physical memory are they are created?

这是平台特定的。通常堆向下生长,堆向上生长。