我正在阅读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的数据部分中分配。
我对此有何不妥?
答案 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 。 ( 图标实际上说明了这一点。底部的灰色容器表示堆栈的静态数组。橙色矩形是由函数调用创建的帧。正如堆叠溢出一样,框架溢出容器和吊杆 - 你的程序已经死了。框架上升的事实说明了堆栈的另一个相当特殊的事情 - 新框架的地址低于旧框架,因此 stackoverflows 实际上发生在堆栈数组的开头而不是它的结尾(除非你认为数组从它们的最大索引开始并以0结尾)。 )
答案 1 :(得分:2)
堆栈本身是静态分配的。随着控制流进入和离开其范围,堆栈中分配的变量会随之而来。
答案 2 :(得分:2)
堆栈以堆栈帧为单位进行分配。
并且,堆栈有助于存储函数参数&amp;局部变量。
函数获取其堆栈帧后,是的,在堆栈帧中,函数使用它的字节作为需要动态。
动态分配堆栈,如堆
如果你想像堆一样在堆栈上分配内存,那么你可以使用alloca()
中的<alloca.h>
,它比堆快,但在大多数情况下你不需要它,它有缺点,因此在一般情况下没有提出。
在不同的上下文中描述堆栈分配可能会更清楚:
thread
的角度来看,(顺便说一下,每个进程默认创建1个线程,作为主线程),堆栈的大小是固定大小&amp;在线程创建时分配(默认情况下,IA-32为2Mb,IA-64为32Mb),您可以根据需要更改默认大小。所以你可以说这是修复和静态。function
视图,当函数启动时,从线程的堆栈内存为堆栈帧分配堆栈帧,当函数完成时堆栈帧消失。 local variable
的角度来看,变量是根据需要动态地从函数的堆栈帧中分配的。所以,如果它被称为静态或动态,你决定。