删除100及以上数值时程序报heap use after free错误如何解决
错误原因分析
- 核心触发原因:
delete函数删除尾节点时未更新全局tail指针。当你删除的节点正好是链表最后一个节点(current == tail)时,仅修改了前驱节点的next指针、释放了原尾节点的内存,但全局tail仍然指向已经被释放的内存地址。后续调用insert执行tail->next = newNode时,就会访问已释放的堆内存,触发Heap use after free错误。 - 为什么仅删除100及以上数值时触发:通常这类场景下数值是按从小到大顺序插入链表,较大的数值默认处于链表尾部,因此删除大数值时命中尾节点删除的逻辑才会触发问题,删除小数值(非尾节点)时不会影响
tail指针的合法性。 - 附带的隐性问题:
insert函数先执行malloc申请内存,再校验重复值,若校验到重复直接返回,会导致刚申请的newNode内存泄漏。delete函数未做空链表校验,若链表为空时调用删除,直接访问head->data会触发空指针崩溃。
修复方案
1. 修正delete函数的尾指针更新逻辑
删除节点时增加尾节点判断,同时补充空链表校验,修改后代码:
void delete(int n){ // 补充空链表判断 if(head == NULL) return; if(head->data == n){ struct Node *tempHead = head; head = head->next; free(tempHead); // 删完头节点后链表为空,同步将tail置为NULL if(head == NULL) tail = NULL; return; } else{ struct Node *current = head; struct Node *prev = NULL; while(current!=NULL && current->data!=n){ prev = current; current = current->next; } if(current==NULL) return; prev->next = current->next; // 如果删除的是尾节点,更新tail为前驱节点 if(current == tail) { tail = prev; } free(current); } }
2. 修正insert函数的内存泄漏问题
将重复校验提前到内存申请之前,同时补充内存申请失败的容错处理:
void insert(int nData) { // 先校验重复,无重复再申请内存 if(checkDuplicates(nData)==1){ return; } struct Node *newNode = (struct Node*)malloc(sizeof(struct Node)+10); // 补充malloc失败校验,避免空指针操作 if(newNode == NULL) return; newNode->data = nData; newNode->next = NULL; if(head == NULL){ head = newNode; tail = newNode; } else { tail->next = newNode; tail = newNode; } }
内容的提问来源于stack exchange,提问作者Kush Patel
相关产品推荐
相关产品推荐

