2. malloc 的魔法:malloc函数原型、参数与返回值
好,咱们正式开始接触动态内存分配的第一个核心函数——malloc。
说实话,我刚开始学C语言那会儿,看到malloc这个名字,第一反应是「这玩意儿是干嘛的?内存还能动态分配?」。后来真正用上了,才发现它就像一把瑞士军刀——用好了,代码灵活又高效;用不好,程序崩溃得莫名其妙。
今天咱们就把malloc的底裤扒干净,看看它到底是怎么工作的。
2.1 函数原型:长什么样?
先看官方定义:
#include <stdlib.h>
void *malloc(size_t size);
嗯,就这么简单。一个函数名,一个参数,一个返回值。
但别小看它。我见过不少新手,甚至工作两三年的工程师,在这个函数上栽过跟头。咱们一个一个拆开看。
2.2 参数:你要多大?
size 参数的类型是 size_t,说白了就是一个无符号整数。它告诉系统:「嘿,给我留这么一大块内存。」
单位是字节。不是比特,不是字,是字节。
举个例子:
int *p = (int *)malloc(4);
这行代码的意思是:向系统申请4个字节的内存,用来存一个 int。
但问题来了——int在不同平台上大小不一样。在32位系统上是4字节,在64位系统上可能还是4字节(取决于编译器),但有些嵌入式平台上可能是2字节。
所以,我个人的习惯是:永远不要写死数字。用 sizeof 运算符:
int *p = (int *)malloc(sizeof(int));
这样,不管平台怎么变,代码都能正确申请到合适的大小。
int *arr = (int *)malloc(10 * sizeof(int));
这样代码更清晰,也更容易维护。
2.3 返回值:成功还是失败?
malloc 返回的是 void *——一个无类型指针。说白了,就是一块内存的起始地址,但系统不知道你要用它存什么类型的数据。
所以我们需要强制类型转换:
int *p = (int *)malloc(sizeof(int));
把 void * 转成 int *,告诉编译器:「这块内存我要用来存int。」
但这里有个关键点:malloc 可能失败。
为什么会失败?内存不够了呗。比如你申请1GB,但系统只剩512MB了,那 malloc 就会返回 NULL。
我曾经在一个嵌入式项目里吃过这个亏。当时申请了一块缓冲区,没检查返回值就直接用了。结果程序跑着跑着就崩了,查了两天才发现是内存不足导致 malloc 返回了 NULL。
所以,每次 malloc 之后,一定要检查返回值:
int *p = (int *)malloc(sizeof(int));
if (p == NULL) {
// 处理错误,比如打印日志、退出程序等
printf("内存分配失败!\n");
return -1;
}
2.4 申请一块整型内存:完整示例
好了,理论说完了,咱们写个完整的例子:
#include <stdio.h>
#include <stdlib.h>
int main() {
// 申请一块整型内存
int *p = (int *)malloc(sizeof(int));
// 检查是否成功
if (p == NULL) {
printf("内存分配失败,程序退出。\n");
return 1;
}
// 使用这块内存
*p = 42;
printf("p 指向的值是:%d\n", *p);
// 释放内存
free(p);
return 0;
}
运行结果:
p 指向的值是:42
你看,流程其实很简单:申请 → 检查 → 使用 → 释放。
嗯,这里要注意:free(p) 这一步很多人会忘。我刚开始写C的时候也经常漏掉,结果程序跑着跑着内存就爆了。后来养成了习惯,每次 malloc 之后,马上写对应的 free,就像配对一样。
2.5 知识体系图
下面这张图帮你理清 malloc 的核心逻辑:
2.6 避坑指南
最后,分享几个我踩过的坑:
- 不要忘记包含头文件:
#include <stdlib.h>是必须的。少了它,编译器会警告,甚至报错。 - 不要对 NULL 指针解引用:如果
malloc返回NULL,你直接*p = 42,程序立马崩溃。 - 不要重复 free:同一块内存只能 free 一次。重复 free 会导致未定义行为,程序可能崩溃,也可能不崩溃——但迟早会出问题。
- 不要忘记 free:每次 malloc 都要有对应的 free。否则内存泄漏,程序跑久了内存就爆了。
我曾经在一个网络服务器项目里,因为忘记 free 一个缓冲区,导致内存泄漏。服务器跑了三天后,内存占用从 50MB 涨到了 2GB,最后被系统 OOM killer 干掉了。从那以后,我每次写 malloc,都会立刻写对应的 free,就像条件反射一样。
好了,malloc 的基本用法就这些。下一节咱们聊聊 calloc 和 realloc,看看它们和 malloc 有什么不同。
公众号:蓝海资料掘金营,微信deep3321