C语言链表相邻节点交换代码在VSCode中出现Segmentation Fault
链表相邻节点交换代码段错误分析与修复
你的代码在VSCode中触发段错误,核心原因是内存未初始化加上边界处理缺失,以下是具体问题和修复方案:
核心错误点
- insert_end函数未初始化新节点的next指针:
malloc分配的堆内存是未初始化的随机值,第一次插入节点时,new_node->next不是NULL。后续遍历链表时,temp->next会指向非法内存,触发段错误。在线编译器可能默认将堆内存清零,所以侥幸运行正常,但GCC等标准编译器不会做这个操作。 - swap函数未处理空链表/单节点情况:如果传入的链表为空,
(*head)->next会直接访问空指针,导致段错误。 - main函数不符合C标准:标准C要求main函数返回类型为
int,而非void。
修复后的代码
#include <stdio.h> #include <stdlib.h> typedef struct node { int val; struct node *next; } node; void insert_end(node **head, int d) { node *new_node = (node *)malloc(sizeof(node)); if (new_node == NULL) { // 增加malloc失败判断 perror("malloc failed"); exit(EXIT_FAILURE); } new_node->val = d; new_node->next = NULL; // 强制初始化next为NULL,从根源避免非法遍历 if (*head == NULL) *head = new_node; else { node *temp = *head; while (temp->next != NULL) temp = temp->next; temp->next = new_node; } } node *swap(node **head) { if (*head == NULL || (*head)->next == NULL) { // 处理空链表或单节点的边界情况 return *head; } node *temp = (node *)malloc(sizeof(node)); if (temp == NULL) { perror("malloc failed"); exit(EXIT_FAILURE); } temp->next = *head; node *start = (*head)->next; while (temp->next != NULL && temp->next->next != NULL) { node *ptr1 = temp->next; node *ptr2 = temp->next->next; temp->next = ptr2; ptr1->next = ptr2->next; ptr2->next = ptr1; temp = ptr1; } free(temp); // 释放临时节点,避免内存泄漏 return start; } void disp(node *head) { while (head != NULL) { printf("%d\n", head->val); head = head->next; } } int main() // 改为标准int返回类型 { int arr[] = { 1, 2, 3 }; int size = sizeof(arr) / sizeof(arr[0]); node *head = NULL; for (int i = 0; i < size; i++) { insert_end(&head, arr[i]); } node *ptr = swap(&head); disp(ptr); // 释放链表内存,避免内存泄漏 node *temp; while (ptr != NULL) { temp = ptr; ptr = ptr->next; free(temp); } return 0; }
关键修复说明
- 强制初始化新节点的next指针:创建新节点后立即将
new_node->next设为NULL,确保链表尾节点始终合法,彻底避免遍历到非法内存。 - 增加malloc失败检查:malloc可能分配失败返回NULL,添加判断可以提前终止程序,避免后续空指针访问。
- swap函数边界处理:先判断链表是否为空或只有一个节点,直接返回原链表,避免空指针访问。
- 释放临时节点:swap中创建的temp节点用完后必须free,否则会造成内存泄漏。
- 修正main函数:改为标准的
int main()并添加return 0,符合C语言规范。 - 添加链表内存释放:程序结束前遍历释放所有节点,养成良好的内存管理习惯。
内容的提问来源于stack exchange,提问作者Ankit Gupta
相关产品推荐
相关产品推荐

