C语言take_quotes内存释放致tokens失效及Valgrind报错问题问询
解决方案
问题根源
strtok不会生成新的子字符串,仅会修改传入的原内存块,返回的指针均指向take_quotes分配的str内存内部,因此提前释放str会导致tokens数组内所有指针变为悬空指针,访问直接失效。- 你改用
strdup复制子串的思路是正确的,Valgrind报内存泄漏来自三个问题:- 异常分支未做完整内存清理:循环中
realloc分配失败时,原代码仅释放了tokens指针数组,没有释放已经用strdup分配的各个子串,也没有释放str本身。 - 调用端未遵循释放规则:
tokenize返回的tokens数组需要按固定规则释放,调用方未做对应操作也会导致内存泄漏。 - 缺少对
take_quotes返回空的判断:如果take_quotes申请内存失败返回NULL,后续strtok会直接触发空指针访问。
- 异常分支未做完整内存清理:循环中
修正后代码
#include <stdlib.h> #include <string.h> #include <stdio.h> // 非POSIX环境可以替换为自定义的strdup实现 static char* my_strdup(const char* s) { if (!s) return NULL; size_t len = strlen(s) + 1; char* dup = malloc(len); if (dup) memcpy(dup, s, len); return dup; } char** tokenize(char* line){ if(line == NULL) return NULL; char* str = take_quotes(line, stderr); // 新增take_quotes返回空的异常处理 if (str == NULL) return NULL; char **tokens = malloc( sizeof( char * ) ); *tokens = NULL; size_t n = 1; const char *delim = " \t \n"; char *p = strtok( str, delim ); int success = p != NULL; while ( success ) { char **tmp = realloc( tokens, ( n + 1 ) * sizeof( char * ) ); if ( tmp == NULL ) { // 新增清理逻辑:释放已经分配的子串 for (size_t i = 0; tokens[i]; i++) { free(tokens[i]); } free( tokens ); tokens = NULL; success = 0; } else { tokens = tmp; // 复制子串,和原str内存脱离依赖 tokens[n - 1] = my_strdup(p); // 处理strdup分配失败的情况 if (tokens[n-1] == NULL) { // 清理已经分配的资源 for (size_t i = 0; i < n-1; i++) { free(tokens[i]); } free(tokens); tokens = NULL; success = 0; break; } tokens[n] = NULL; ++n; p = strtok( NULL, delim ); success = p != NULL; } } // 现在释放str不会影响tokens里的内容 free(str); str = NULL; return tokens; }
调用端正确释放方式
返回的tokens数组以NULL作为结束标记,使用完后需要先逐个释放每个子串,再释放指针数组本身:
// 调用示例 char** tokens = tokenize("Hello \"nice\" day"); if (tokens != NULL) { // 这里写使用tokens的业务逻辑 for (size_t i = 0; tokens[i] != NULL; i++) { printf("token %zu: %s\n", i, tokens[i]); } // 释放逻辑 for (size_t i = 0; tokens[i] != NULL; i++) { free(tokens[i]); // 先释放每个子字符串 } free(tokens); // 最后释放指针数组 }
按照以上逻辑修改后,take_quotes分配的内存可以在tokenize内部正常释放,也不会出现内存泄漏问题。
内容的提问来源于stack exchange,提问作者p20xx
相关产品推荐
相关产品推荐

