118 / 163 · C11 · 约 8 分钟
插曲:内存API
先记住这句话
C程序依赖栈上的自动分配和堆上的显式请求来管理数据寿命。理解malloc与free的正确配对以及常见误用,是写出健壮软件的关键。
程序内存的两种类型
函数内部声明的变量由编译器在调用栈上自动预留空间,函数返回时这些空间立刻失效。需要跨越函数调用继续存在的数据必须放到堆上,程序员负责提出请求并在用完后归还。
正确调用malloc
向malloc传入所需字节数,通常用sizeof作用于类型来计算。返回的void指针再转换成目标类型。务必检查是否为NULL。复制字符串时额外加一字节存放结束符。
释放内存和典型陷阱
每次成功的malloc最终必须用同一指针调用free。完全忘记分配、少申请一字节或重复释放都会导致崩溃或安全问题。许多新语言用垃圾回收隐藏这些细节。
常见误区
- 把未初始化的指针交给strcpy当目标
- 只申请strlen字节随后连结束符一起写入
- 用完堆块却从不调用free
运行一个例子
最低标准 C11 · 完整程序 · 下载 .c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
int stack_val = 42;
printf("Allocated on stack: %d\n", stack_val);
int *heap_val = (int *)malloc(sizeof(int));
if (heap_val == NULL) {
printf("Heap allocation failed\n");
return 1;
}
*heap_val = 99;
printf("Allocated on heap: %d\n", *heap_val);
const char *original = "OSTEP";
char *copy = (char *)malloc(strlen(original) + 1);
if (copy == NULL) {
free(heap_val);
printf("String allocation failed\n");
return 1;
}
strcpy(copy, original);
printf("String copy: %s\n", copy);
free(copy);
free(heap_val);
printf("All heap memory released\n");
return 0;
}
在本地编译
gcc -std=c11 -Wall -Wextra -Wpedantic -Werror ostep-14-memory-api.c -o example && ./example预期结果
Allocated on stack: 42
Allocated on heap: 99
String copy: OSTEP
All heap memory released
CHECK YOUR UNDERSTANDING
合上答案,试着解释。
为什么对动态分配得到的指针做sizeof只会得到指针本身的宽度?
查看参考答案
sizeof是编译期操作符,它只看见变量的静态类型,看不见运行时真正申请了多少字节。
继续查证
标准草案与官方章节会更新;版本标记只说明示例最低要求。