堆栈中的变量是“静态分配的”吗?

时间:2015-10-10 17:32:45

标签: c stack heap dynamic-allocation static-allocation

我正在阅读this article,并看到了这一点:“这篇文章假设你已经知道并至少基本上了解了记忆的方式 在GNU / Linux系统中工作的地图,特别是静态内存的区别 在堆中分配并在堆中动态分配内存。“

这使我感到困惑,因为我认为堆栈和堆是动态分配的,这意味着只在必要时才进行分配,并且在函数内部声明为“静态”的全局变量和变量是静态分配的,这意味着总是分配。

例如,如果我有

void f() {
    int x = 1;
    ...
}

值1只被放在堆栈上,如果函数f()被调用,堆栈指针只会递增。同样,如果我有

void f() {
    int x = malloc(1 * sizeof(int));
    ...
}

只有在调用f()时才会分配堆内存。但是,如果我有“int x = 1;”在程序的全局部分或“static int x = 1;”在函数体内,每次运行该程序时,该内存都将在值为1的数据部分中分配。

我对此有何不妥?

3 个答案:

答案 0 :(得分:3)

静态变量只初始化一次,即使初始化语句在函数体内。

检查wikipedia示例:

#include <stdio.h>

void func() {
    static int x = 0; 
    /* x is initialized only once across five calls of func() and
      the variable will get incremented five 
      times after these calls. The final value of x will be 5. */
    x++;
    printf("%d\n", x); // outputs the value of x
}

int main() { //int argc, char *argv[] inside the main is optional in the particular program
    func(); // prints 1
    func(); // prints 2
    func(); // prints 3
    func(); // prints 4
    func(); // prints 5
        return 0;
}

堆栈基本上是一个静态分配的大型数组,其中一个可移动指针从它的开头开始。当你调用一个函数(从w / main开始)时,指针移动(创建一个堆栈框架)并且堆栈框架中的空间被切片并赋予局部变量(你有多少局部变量决定你的函数的堆栈框架有多大)将会)。因此局部变量是一种动态的(它们只有在你进入函数时才会出现),但是堆栈是静态大小的。如果你在它上面分配一个超大型结构或使用过多的递归,你将会超越结束,操作系统会让你失望 - 这种现象称为 stackoverflow 。 ( stackoverflow icon图标实际上说明了这一点。底部的灰色容器表示堆栈的静态数组。橙色矩形是由函数调用创建的帧。正如堆叠溢出一样,框架溢出容器和吊杆 - 你的程序已经死了。框架上升的事实说明了堆栈的另一个相当特殊的事情 - 新框架的地址低于旧框架,因此 stackoverflows 实际上发生在堆栈数组的开头而不是它的结尾(除非你认为数组从它们的最大索引开始并以0结尾)。 )

答案 1 :(得分:2)

堆栈本身是静态分配的。随着控制流进入和离开其范围,堆栈中分配的变量会随之而来。

答案 2 :(得分:2)

堆栈以堆栈帧为单位进行分配。

  • 调用函数时,会为其分配堆栈帧,
  • 当函数返回时,其堆栈框架消失,

并且,堆栈有助于存储函数参数&amp;局部变量。

函数获取其堆栈帧后,是的,在堆栈帧中,函数使用它的字节作为需要动态。

动态分配堆栈,如堆

如果你想像堆一样在堆栈上分配内存,那么你可以使用alloca()中的<alloca.h>,它比堆快,但在大多数情况下你不需要它,它有缺点,因此在一般情况下没有提出。

在不同的上下文中描述堆栈分配可能会更清楚:

  • 从linux thread的角度来看,(顺便说一下,每个进程默认创建1个线程,作为主线程),堆栈的大小是固定大小&amp;在线程创建时分配(默认情况下,IA-32为2Mb,IA-64为32Mb),您可以根据需要更改默认大小。所以你可以说这是修复和静态。
  • 从线程或进程内的function视图,当函数启动时,从线程的堆栈内存为堆栈帧分配堆栈帧,当函数完成时堆栈帧消失。
  • 从函数内部的非静态local variable的角度来看,变量是根据需要动态地从函数的堆栈帧中分配的。

所以,如果它被称为静态或动态,你决定。