1. 栈(stack)
栈用于存储函数(包括主函数)内部使用的变量,是一个先进先出(LIFO)结构,每次声明一个新变量,都会将其推入栈中。当函数运行结束时,栈上上与该函数所有相关的变量(称为一个栈帧)将被释放。栈由CPU自动管理,用户不必关心如何分配和释放内存。栈内存分为栈帧,每次函数调用都会为其分配一个栈帧,在函数返回时释放。
栈的大小通常有限,如果程序试图将过多的信息放入栈中,就会出现栈溢出
。
栈的先进后出并不是指栈中的变量是先进后出的,而是指"栈帧"的先进后出,这保证了函数的调用顺序。
- 栈内存由CPU管理
- 变量自动分配和释放
- 栈的大小有限制
- 当变量创建和销毁时,栈会增长和收缩
2. 堆(heap)
堆是一块大的内存,支持动态分配,由用户负责管理。可以通过malloc
方法分配内存,通过free
方法回收内存,若内存使用后没有回收,则会导致"内存泄漏",即这块内存无法被其他进程所用。
与栈不同,除物理内存大小的限制,堆的大小没有严格限制。在堆中创建的变量可在程序的任何地方访问(全局变量)。
- 堆内存由程序员管理
- 在C中,使用
malloc
和free
来分配和释放堆内存 - 需要用指针访问堆
3.
考虑以下程序
#include <stdio.h>
#include <stdlib.h>
int x;
int main(void)
{
int y;
char *str;
y = 4;
printf("stack memory: %d\n", y);
str = malloc(100 * sizeof(char));
str[0] = 'm';
printf("heap memory: %c\n", str[0]);
free(str);
return 0;
}
在上面这段程序中,x
是一个全局变量,y
和str
都是局部变量。malloc
为str
在堆上分配了100个字节的内存,free
则释放了分配的这些内存。
参数 | 堆 | 堆 |
---|---|---|
数据结构类型 | 堆栈是线性数据结构。 | 堆是一个层次数据结构。 |
访问速度 | 高速访问 | 与堆栈相比速度较慢 |
空间管理 | 空间由操作系统高效管理,因此内存永远不会变得支离破碎。 | 堆空间没有有效地使用。当内存块首先分配然后释放时,内存可能会变得支离破碎。 |
访问 | 仅限本地变量 | 它允许您在全球范围内访问变量。 |
空间大小限制 | 取决于操作系统的堆栈大小限制。 | 内存大小没有特定的限制。 |
调整 | 变量无法重新缩放 | 变量可以重新缩放。 |
内存分配 | 内存被分配到一个连续块中。 | 内存以任意随机顺序分配。 |
分配和交易定位 | 通过编译器说明自动完成。 | 它由程序员手动完成。 |
释放 | 不需要去分配变量。 | 需要明确去分配。 |
成本 | 少 | 更多 |
实现 | 基于简单阵列、使用动态内存和基于链接列表的 3 种方式可以实现堆栈。 | 堆可以使用阵列和树木实现。 |
主要问题 | 内存不足 | 内存碎片 |
参考地区 | 自动编译时间说明。 | 足够 |
灵活性 | 固定尺寸 | 调整大小是可能的 |
访问时间 | 更快 | 慢 |