- 内存分配函数使用:
malloc
:
malloc
函数用于分配指定字节数的内存空间。其原型为void *malloc(size_t size)
。例如,要分配一个大小为n
个int
类型的数组空间,可以这样写:
int *arr = (int *)malloc(n * sizeof(int));
if (arr == NULL) {
// 处理内存分配失败的情况,比如输出错误信息并退出程序
perror("malloc");
exit(EXIT_FAILURE);
}
calloc
:
calloc
函数用于分配指定数量和指定大小的内存块,并将所分配的内存块初始化为零。其原型为void *calloc(size_t nmemb, size_t size)
。例如,要分配n
个int
类型的数组空间并初始化为0,可以这样写:
int *arr = (int *)calloc(n, sizeof(int));
if (arr == NULL) {
perror("calloc");
exit(EXIT_FAILURE);
}
realloc
:
realloc
函数用于改变已分配内存块的大小。其原型为void *realloc(void *ptr, size_t size)
。如果ptr
为NULL
,realloc
的行为就和malloc
一样;如果size
为0,并且ptr
指向一个合法的内存块,realloc
会释放该内存块并返回NULL
。例如,假设已经有一个动态分配的数组arr
,要扩展其大小:
int *new_arr = (int *)realloc(arr, new_n * sizeof(int));
if (new_arr == NULL) {
// 处理内存重新分配失败的情况
perror("realloc");
// 可以考虑保留原有的arr数据,不进行释放,根据具体需求决定
// free(arr);
// arr = NULL;
} else {
arr = new_arr;
}
- 内存释放函数
free
:
- 使用
free
函数来释放通过malloc
、calloc
或realloc
分配的内存。例如:
free(arr);
arr = NULL; // 防止悬空指针
- 内存泄漏定位和解决方法:
- 工具辅助:
- Valgrind:在Linux系统下,可以使用Valgrind工具。例如,编译程序时确保使用
-g
选项保留调试信息(gcc -g -o program program.c
),然后使用valgrind --leak-check=full./program
运行程序。Valgrind会详细报告内存泄漏的位置,包括在哪个源文件、哪一行代码发生了内存泄漏。
- AddressSanitizer:在GCC和Clang编译器中都支持AddressSanitizer。编译时添加
-fsanitize=address
选项(gcc -fsanitize=address -g -o program program.c
),运行程序时,它会检测到内存泄漏并输出详细的错误信息,指出内存分配和未释放的位置。
- 代码审查:
- 仔细检查代码中
malloc
、calloc
、realloc
和free
的配对使用。确保每个分配函数都有对应的free
调用,并且free
的调用时机正确。例如,在函数返回前,检查是否有未释放的动态分配内存。
- 添加日志:
- 在内存分配和释放的地方添加日志输出。例如,使用
printf
函数记录每次malloc
、calloc
、realloc
和free
的调用,包括分配的大小、地址等信息。这样在程序运行后,可以通过分析日志来查找可能的内存泄漏点。
#include <stdio.h>
#include <stdlib.h>
void *my_malloc(size_t size) {
void *ptr = malloc(size);
if (ptr) {
printf("malloc: allocated %zu bytes at %p\n", size, ptr);
} else {
printf("malloc: allocation failed\n");
}
return ptr;
}
void my_free(void *ptr) {
if (ptr) {
printf("free: releasing memory at %p\n", ptr);
free(ptr);
}
}
int main() {
int *arr = (int *)my_malloc(10 * sizeof(int));
// 使用arr...
my_free(arr);
return 0;
}