在c语言的标准库中,malloc是一个用于动态内存分配的核心函数,全称是memory allocation,它的作用是让程序在运行过程中,根据实际需求向系统的堆区申请一块指定大小的连续内存空间,供程序后续使用。

malloc的基本定义与函数原型
malloc是声明在<stdlib.h>头文件中的函数,它的函数原型如下:
#include <stdlib.h> void* malloc(size_t size);
参数size表示需要申请的内存空间大小,单位是字节。函数的返回值是一个void类型的指针,如果内存申请成功,返回的是指向申请到的内存块起始地址的指针;如果申请失败,会返回NULL指针。
malloc的使用场景
当我们在编写c语言程序时,如果无法提前确定需要使用的内存大小,或者需要的内存大小超过了栈区的默认容量,就可以使用malloc来动态申请内存。常见的使用场景包括:
- 存储长度不确定的字符串或数组
- 创建动态大小的数据结构,比如链表、动态数组
- 需要在函数之间传递大块数据,避免栈溢出
malloc的使用示例
下面是一个简单的使用示例,演示如何用malloc申请一个可以存储10个int类型元素的数组:
#include <stdio.h>
#include <stdlib.h>
int main() {
// 申请10个int类型大小的内存空间,sizeof(int)获取单个int的字节数
int *arr = (int*)malloc(10 * sizeof(int));
// 判断内存是否申请成功
if (arr == NULL) {
printf("内存申请失败n");
return 1;
}
// 给申请到的内存赋值
for (int i = 0; i < 10; i++) {
arr[i] = i * 2;
}
// 打印数组内容
for (int i = 0; i < 10; i++) {
printf("%d ", arr[i]);
}
printf("n");
// 使用完内存后释放,避免内存泄漏
free(arr);
// 将指针置为NULL,避免野指针
arr = NULL;
return 0;
}
使用malloc的注意事项
1. 检查返回值
malloc申请内存有可能失败,因此每次调用malloc之后,都需要判断返回的指针是否为NULL,避免后续对空指针进行操作导致程序崩溃。
2. 手动释放内存
malloc申请的内存位于堆区,不会随着函数的结束自动释放,因此使用完这块内存之后,必须调用<stdlib.h>中的free函数来手动释放,否则会造成内存泄漏。
3. 避免野指针
释放内存之后,原来的指针仍然指向已经被释放的内存地址,这时候它就变成了野指针,后续如果误用这个指针会造成不可预期的错误,因此释放内存之后最好将指针赋值为NULL。
4. 不要重复释放
对同一块malloc申请的内存重复调用free函数,会导致程序出现未定义行为,甚至直接崩溃,因此要确保每块动态申请的内存只被释放一次。
5. 申请的内存不会初始化
malloc申请到的内存中存储的是之前遗留的随机数据,不会被初始化为0,如果需要初始化的内存,可以使用calloc函数,或者在申请之后手动赋值。
malloc和calloc、realloc的区别
c语言中还有另外两个动态内存分配相关的函数,和malloc的区别如下:
| 函数名 | 功能 | 是否初始化 |
|---|---|---|
| calloc | 申请指定数量和大小的内存块 | 是,会初始化为0 |
| malloc | 申请指定字节数的内存块 | 否,保留原有随机数据 |
| realloc | 调整已经申请的内存块的大小 | 原有数据保留,新增部分不初始化 |
注意:realloc如果调整内存大小的时候,原来的内存块后面没有足够的连续空间,会重新申请一块更大的内存,把原有数据拷贝过去,然后释放原来的内存块,因此调用realloc之后,原来的指针可能会失效,需要用新的返回值覆盖原来的指针。