释放regex_t数组结构体时遇SEGV错误与内存泄漏问题求助
问题分析与解决方案
核心问题
代码崩溃的根本原因是对regex_t结构体进行了浅拷贝,导致多个regex_t实例共享同一块内部动态内存,最终触发重复释放(Double Free)或访问已释放内存的错误:
add_pat函数中直接赋值regex_t结构体:patterns->elem[num] = new_pat;,而regex_t内部包含动态分配的正则表达式数据,直接拷贝会让两个实例共享同一块内存。- 最小复现代码中重复使用同一个
new_reg变量两次调用regcomp,且未在中间调用regfree,属于未定义行为,会导致内存泄漏或内部数据混乱。 - 开启
regfree循环时,数组元素和main中的new_reg会重复释放同一块内存,触发SEGV错误;注释循环时,数组内regex_t的内部内存未被释放,导致内存泄漏。
修复方案
方案1:在数组元素上直接编译正则(推荐)
避免传递已编译好的regex_t,改为传递模式字符串和编译标志,在add_pat内部为新元素编译正则,确保每个实例独立:
reg_arr* add_pat(reg_arr* patterns, const char* pattern, int I_flag, int* flag) { int num = patterns->num; regex_t* temp = realloc(patterns->elem, (num + 1) * sizeof(regex_t)); if (temp) { patterns->elem = temp; // 直接在新数组元素上编译正则 int res = I_flag ? regcomp(&patterns->elem[num], pattern, REG_ICASE) : regcomp(&patterns->elem[num], pattern, 0); if (res == 0) { patterns->num = num + 1; } else { // 编译失败,回滚内存分配 free(temp); *flag = 0; } } else { *flag = 0; } return patterns; }
调整main调用逻辑:
int check = 1; reg_arr* pats = init_regex(&check); if (check) pats = add_pat(pats, "word", 0, &check); if (check) pats = add_pat(pats, "int", 0, &check); free_reg(pats);
方案2:使用regdup复制正则实例(平台依赖)
部分POSIX系统提供regdup函数,可复制已编译的regex_t生成独立副本:
reg_arr* add_pat(reg_arr* patterns, const regex_t* new_pat, int* flag) { int num = patterns->num; regex_t* temp = realloc(patterns->elem, (num + 1) * sizeof(regex_t)); if (temp) { patterns->elem = temp; // 复制正则实例 if (regdup(&patterns->elem[num], new_pat) == 0) { patterns->num = num + 1; } else { free(temp); *flag = 0; } } else { *flag = 0; } return patterns; }
注意:regdup并非所有平台都支持,需确认编译环境是否提供该函数。
修复free_reg函数
无论采用哪种方案,都需要正确释放每个regex_t的内部内存:
void free_reg(reg_arr *reg) { if (reg) { for (int i = 0; i < reg->num; i++) { regfree(®->elem[i]); } free(reg->elem); free(reg); } }
额外注意事项
- 禁止重复使用同一个
regex_t变量调用regcomp而不先调用regfree,这会导致内存泄漏和未定义行为。 - 确保所有动态分配的内存(包括
regex_t内部内存)都被正确释放,避免泄漏或重复释放。
内容的提问来源于stack exchange,提问作者plush guardian
相关产品推荐
相关产品推荐

