C 语言的动态内存管理是通过 malloc
、calloc
、realloc
和 free
这四个标准库函数来完成的,这些函数定义在 <stdlib.h>
头文件中。
1. 动态内存管理的基本函数
函数 | 作用 |
malloc(size_t size) | 分配 指定字节 的内存,未初始化 |
calloc(size_t num, size_t size) | 分配 指定数量和大小 的内存,并初始化为 0 |
realloc(void *ptr, size_t new_size) | 重新调整已分配的内存大小 |
free(void *ptr) | 释放已分配的内存 |
2. malloc()
(分配内存,不初始化)
malloc
分配一块指定大小的内存,并返回指向该内存的指针。
⚠️ 注意:malloc
只分配空间,不会初始化内存!
示例:使用 malloc
分配动态数组
#include <stdio.h>
#include <stdlib.h>
int main() {
int *arr = (int *)malloc(5 * sizeof(int)); // 分配 5 个 int 大小的内存
if (arr == NULL) {
printf("内存分配失败!\n");
return 1;
}
// 赋值并输出
for (int i = 0; i < 5; i++) {
arr[i] = i + 1;
printf("%d ", arr[i]); // ⚠️ malloc 分配的内存未初始化,建议手动赋值!
}
printf("\n");
free(arr); // 释放内存
return 0;
}
输出:
1 2 3 4 5
3. calloc()
(分配并初始化)
calloc(n, size)
分配 n * size
字节的内存,并初始化为 0。
示例:使用 calloc
分配动态数组、
#include <stdio.h>
#include <stdlib.h>
int main() {
int *arr = (int *)calloc(5, sizeof(int)); // 分配 5 个 int,并初始化为 0
if (arr == NULL) {
printf("内存分配失败!\n");
return 1;
}
// 输出默认值(全部初始化为 0)
for (int i = 0; i < 5; i++) {
printf("%d ", arr[i]); // 结果全部是 0
}
printf("\n");
free(arr); // 释放内存
return 0;
}
输出:
0 0 0 0 0
✅ calloc
适用于初始化为 0 的情况,如二维数组、结构体等。
4. realloc()
(调整已分配的内存)
realloc(ptr, new_size)
调整 之前 malloc
或 calloc
分配的内存大小。
示例:动态扩展数组
#include <stdio.h>
#include <stdlib.h>
int main() {
int *arr = (int *)malloc(3 * sizeof(int)); // 分配 3 个 int
if (arr == NULL) return 1;
arr[0] = 1; arr[1] = 2; arr[2] = 3;
// 重新调整大小为 5 个 int
arr = (int *)realloc(arr, 5 * sizeof(int));
if (arr == NULL) return 1;
arr[3] = 4;
arr[4] = 5;
for (int i = 0; i < 5; i++) {
printf("%d ", arr[i]);
}
printf("\n");
free(arr);
return 0;
}
输出:
1 2 3 4 5
⚠️ 注意:
realloc
可能会移动数据,返回的新指针可能不同于原来的指针,所以要用arr = realloc(arr, new_size)
重新赋值。- 如果
realloc
失败,它会返回NULL
,原来的数据不会丢失,但要确保代码能正确处理。
5. free()
(释放内存)
所有使用 malloc
、calloc
、realloc
分配的内存,必须使用 free
释放,否则会导致内存泄漏!
示例:正确释放内存
#include <stdio.h>
#include <stdlib.h>
int main() {
int *ptr = (int *)malloc(10 * sizeof(int));
if (ptr == NULL) return 1;
free(ptr); // 释放内存
// 释放后指针仍然存储原来的地址,应该置 NULL
ptr = NULL; // 防止 "野指针" 问题
return 0;
}
⚠️ 释放内存后,不要再使用该指针!
free(ptr);
printf("%d", *ptr); // ❌ 释放后访问是"未定义行为"
6. 内存泄漏与最佳实践
内存泄漏的示例
如果 malloc
了内存但没有 free
,会导致内存泄漏:
void leakMemory() {
int *p = (int *)malloc(100 * sizeof(int));
// ❌ 忘记 free(p),导致内存泄漏!
}
如何避免内存泄漏?
✅ 使用 free
释放所有 malloc
的内存
int *p = (int *)malloc(100 * sizeof(int));
if (p != NULL) {
free(p); // 释放内存
p = NULL; // 避免野指针
}
✅ 动态分配后立即 free
void example() {
int *arr = (int *)malloc(10 * sizeof(int));
if (!arr) return;
// 业务逻辑...
free(arr); // 释放内存
}
✅ 使用智能指针(C++ 适用) 如果是 C++,可以用 std::unique_ptr
或 std::shared_ptr
自动管理内存:
#include <memory>
void example() {
std::unique_ptr<int[]> arr(new int[10]); // 自动释放,无需手动 free()
}
总结
函数 | 作用 | 初始化 | 失败时返回 |
---|---|---|---|
malloc(size) | 分配 size 字节 | ❌ 不初始化 | NULL |
calloc(n, size) | 分配 n * size 字节 | ✅ 初始化为 0 | NULL |
realloc(ptr, new_size) | 调整 ptr 指向的新大小 | ❌ 可能部分保留数据 | NULL (失败时原数据仍然有效) |
free(ptr) | 释放 ptr 指向的内存 | – | – |
THE END
暂无评论内容