如何在给定代码中正确使用malloc以避免程序崩溃?
问题分析与修复方案
1. sl_shallow_copy函数的核心问题
你的sl_shallow_copy只分配了一个链表节点,却试图遍历整个原链表,直接导致程序崩溃:
- 初始分配的
shallow节点的next是未初始化的垃圾值,第一次循环后shallow = shallow->next会指向无效内存; - 没有为原链表的每个元素分配新节点,无法复制完整的链表结构;
- 最终返回的是遍历到末尾的无效指针,而非拷贝链表的头节点。
修复后的sl_shallow_copy:
slist *sl_shallow_copy(slist *strings) { slist *head = NULL; slist **tail = &head; // 用指针的指针跟踪链表尾部 while (strings != NULL) { // 为每个元素分配新节点 *tail = malloc(sizeof(slist)); (*tail)->s = strings->s; // 浅拷贝:仅复制字符串指针 (*tail)->next = NULL; // 初始化next为NULL tail = &((*tail)->next); // 移动尾部指针到下一个位置 strings = strings->next; } return head; }
2. sl_free函数的问题
你的sl_free会释放每个节点的s指针,但如果是浅拷贝链表,s指针与原链表共享内存,会引发:
- 原链表的
s指针变成悬空指针; - 若原链表也调用
sl_free,会触发双重释放崩溃。
解决方案是提供两种释放函数适配不同场景:
// 仅释放链表节点(用于浅拷贝链表,不释放共享的字符串) void sl_free_shallow(slist *strings) { if (strings != NULL) { sl_free_shallow(strings->next); free(strings); } } // 释放链表节点和字符串(用于拥有字符串所有权的链表,比如sl_cons创建的链表,前提是s由malloc分配) void sl_free_deep(slist *strings) { if (strings != NULL) { sl_free_deep(strings->next); free(strings->s); free(strings); } }
3. 额外注意事项
- 调用
sl_cons时,确保传入的s是malloc分配的内存,否则sl_free_deep会因释放非堆内存崩溃; - 无需对
malloc的返回值强制类型转换(C中不必要,还可能隐藏stdlib.h未包含的错误); - 建议检查
malloc返回值是否为NULL,避免内存分配失败引发后续错误。
内容的提问来源于stack exchange,提问作者DevFish
相关产品推荐
相关产品推荐

