首页 文章

堆栈和堆内存的大小[重复]

提问于
浏览
38

可能重复:堆栈和堆的内容和位置是什么?

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

  • 该语言使用两个主要数据结构 stackheap .

  • 创建堆栈以存储子程序的局部变量和簿记数据

  • 创建堆以存储程序的动态分配变量

  • 堆本质上是可变长度的 . (在堆栈上不太确定)

  • 通常,编译器/语言的责任是在执行之前请求OS创建这些数据结构 .

问题

  • 创建堆栈/堆的初始大小是多少?谁来决定呢?

  • 其中是否创建了物理内存?我看到一般描述为 "Stack is created in the top-level-address and the heap at the low-level-address" 请详细说明

4 回答

  • 3

    “堆栈是在顶级地址中创建的,堆是在低级别地址”请详细说明

    这是一个神话 . 它可能具有历史真相的基础 . 它有时可能会与您在现实生活中看到的事物产生共鸣 . 但这不是真的 .

    但是,探索很容易:

    #include <stdlib.h>
    #include <stdio.h>
    
    void check(int depth) {
        char c;
        char *ptr = malloc(1);
        printf("stack at %p, heap at %p\n", &c, ptr);
        if (depth <= 0) return;
        check(depth-1);
    }
    
    int main() {
        check(10);
        return 0;
    }
    

    在我的机器上,我看到:

    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 函数是尾递归的,在一些带有一些编译器选项的实现中你可能会看到堆栈根本没有移动 . 这告诉你一些关于为什么标准没有强制要求所有这些如何工作的东西 - 如果它这样做可能会无意中禁止有用的优化 .

  • 54

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

    msdn

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

    ulimit -s or -a
    

    在我的Linux薄荷64位上它显示8192 KB .

    加载到内存中的每个程序都有几个段 . 在汇编中,可以使用.data,.code等前缀(intelx86)指示每个 .

    它是具有多个子部分的数据段 . 除了其他几个,堆栈和堆都是它的一部分 .

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

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

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

    这两个部分在相反方向上增长的原因是为了最大化其组合存储器的利用率 . 请注意,正如评论中所提到的,这不是一个标准,但大多数常见的操作系统都实现了这一点 .

    ------堆栈启动-----------堆栈向下增长

    --------除非他们互相交叉,否则程序可以运行 .

    -------堆启动------------堆向上增长

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

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

  • 8

    创建堆栈/堆的初始大小是多少?谁来决定呢?

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

    在哪里创建物理内存?我看到一般描述为“堆在顶层地址中创建,堆栈在低层地址” .

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

    真 . 语言标准不要求最小堆栈大小,也不指定堆栈或堆在内存中的位置 . 其原因是使C程序更少依赖于这些细节,因此更容易移植到不同的平台(阅读:不同的操作系统,不同的CPU,不同的编译器) .

  • 12

    首先,C标准没有对平台如何实现堆栈/堆提出任何要求 .

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

    通常,OS为每个进程分配固定大小的 stack ,这是特定于平台的 . 堆大小没有限制,程序通常具有所有可用的虚拟地址空间 .

    Wherein physical memory are they are created?

    这是特定于平台的 . 通常堆栈向下增长并且堆积增长 .

相关问题