C语言代码未调用free()也可正常运行,该写法是否合规?
内存释放逻辑说明
你不能在ft_append内部释放newstr的原因很明确:*str = newstr已经把newstr指向的内存地址赋值给了外部传入的指针,这块内存后续还要在main函数中使用,提前释放会导致后续访问非法内存,自然无法正常输出。
你当前的代码还存在两个未定义行为/隐患:
main函数中定义的char *str没有初始化,属于野指针,其值是随机的,不一定为NULL。你在ft_strlen中判断if(str)的逻辑只有在str为NULL时才生效,野指针会大概率触发非法内存访问崩溃,你现在能正常运行只是巧合,必须改为char *str = NULL;- 每次
ft_append申请新内存拷贝完旧字符串内容后,旧字符串对应的内存没有被释放,会产生内存泄漏。
正确实现代码
修正后的ft_append逻辑如下,只需要释放已经没用的旧内存即可:
void ft_append(char **str, char c) { int len = ft_strlen(*str); char *old_str = *str; // 保存旧内存地址 char *newstr = malloc(len + 2); // 增加malloc失败判断,避免空指针访问 if (!newstr) { perror("malloc申请内存失败"); return; } int i = 0; if (len != 0) { while (i < len) { newstr[i] = old_str[i]; i++; } } newstr[i] = c; newstr[i + 1] = '\0'; *str = newstr; free(old_str); // 释放已经不需要的旧内存,free(NULL)是C标准允许的安全操作 }
main函数的修正和最终释放逻辑:
int main() { char *str = NULL; // 必须初始化为NULL ft_append(&str, 'x'); ft_append(&str, 'y'); ft_append(&str, 'z'); printf("str = %s\n", str); free(str); // 所有使用结束后再释放最终拼接好的字符串内存 return 0; }
核心原则总结
malloc申请的堆内存释放的唯一标准:确认这块内存后续不会被任何指针访问时,才可以调用free释放。
newstr对应的内存需要返回给外部使用,所以绝对不能在ft_append内部释放- 旧字符串对应的内存,拷贝完成后没有任何指针会再访问,可以在
ft_append内释放 - 最终拼接完成的字符串,在
main函数使用完毕后再释放即可
内容的提问来源于stack exchange,提问作者Dudu Krem
相关产品推荐
相关产品推荐

