C程序malloc内存管理释放未分配指针,leaks检测无内存泄漏
问题根因
你的代码存在3个核心错误,直接导致运行时释放非法指针报错:
manipulate函数返回的字符串数组缺少终止哨兵
你申请了argc + 1长度的指针数组空间,但只填充了前argc个元素,最后一个位置没有手动赋值为NULL。main函数中循环判断*p && *q的逻辑依赖哨兵终止,此时属于未定义行为。free_args可变参数逻辑完全错误
- 循环条件
i < **args逻辑完全不成立:**args取的是第一个字符串数组首个元素的首字符ASCII值(比如程序名第一个字符是.,ASCII值为46),会导致循环执行远超过你传入参数数量的次数,读取非法内存。 - 你传入
free_args的是char**类型的字符串数组,但va_arg却按char*类型读取,类型不匹配,拿到的都是非法指针。 - 释放逻辑缺失:你既没有释放每个字符串数组内单独malloc的字符串,也没有释放字符串数组本身的内存。
- 额外的逻辑瑕疵:main函数循环中对
argv执行++argv操作属于没必要的修改,虽然不直接导致崩溃,但不符合常规写法。
修复方案
1. 修复manipulate函数,添加终止哨兵
char **manipulate(int argc, const char *const *argv, int (*const change)(int)){ char **retArr = malloc((argc+1) * sizeof(char*)); for (int i = 0; i < argc; ++i) { const char *const str = argv[i]; size_t len = strlen(str); char* modified = malloc((len+1) * sizeof(char)); for (size_t j = 0; j < (len+1); ++j) { modified[j] = change(str[j]); } retArr[i] = modified; } retArr[argc] = NULL; // 新增:设置数组终止哨兵 return retArr; }
2. 重写内存释放函数
推荐直接写单独的字符串数组释放函数,逻辑更清晰:
void free_str_array(char **arr) { // 先释放数组内每个单独申请的字符串 for (char **p = arr; *p; p++) { free(*p); } // 再释放字符串数组本身的内存 free(arr); }
main函数中替换原来的free_args调用即可:
free_str_array(upArgs); free_str_array(lowArgs);
如果要保留可变参数的写法,修改为如下版本:
void free_args(char **first, ...) { va_list ap; va_start(ap, first); char **arr = first; // 读到NULL哨兵停止 while (arr) { for (int i = 0; arr[i]; i++) { free(arr[i]); } free(arr); arr = va_arg(ap, char**); } va_end(ap); }
原来的调用逻辑free_args(upArgs, lowArgs, NULL);可直接复用。
为什么leaks检测不到泄漏
leaks -atExit 只会在程序正常退出时扫描进程内存泄漏,你运行./test时程序执行到free_args就直接崩溃终止,操作系统会自动回收进程占用的所有内存,因此扫描不到残留的内存泄漏。
内容的提问来源于stack exchange,提问作者Redman
相关产品推荐
相关产品推荐

