如何修复C代码中的SIGSEGV(段错误)问题
单链表添加节点触发SIGSEGV错误排查
我正在编写一个C程序,读取文件中用括号分隔的句子并解析为“room”,再以动态分配的节点形式添加到动态分配的单链表结构中。gdb标记add_to_list(const room_t *room, list *list)函数中的current->next = createnode(room);行触发了SIGSEGV(地址边界错误)。
相关代码与结构体定义
核心函数代码
void create_room(char *text, list *list) { unsigned int index; color_t color; char *description; parse_curly_brackets(text, &index, &color); room_t *new_room = (room_t *)malloc(sizeof(room_t)); new_room->index = index; new_room->color = color; char *ptr = strchr(text, '}'); if (ptr != NULL) { ptr = strchr(ptr + 1, '}'); if (ptr != NULL) { ptr++; while (*ptr != '\0' && (*ptr == ' ' || *ptr == '\n')) ptr++; description = ptr; new_room->description = (char *)malloc(strlen(description)); strcpy(new_room->description, description); } else { printf("Second closing curly brace not found\n"); free(new_room); return; } } else { printf("Closing curly brace not found\n"); free(new_room); return; } add_to_list(new_room, list); } node_t *createnode (const room_t *room) { node_t *newnode = malloc(sizeof(node_t)); if (!newnode) { return NULL; } newnode->data = room; newnode->next = NULL; return newnode; }; void add_to_list (const room_t *room, list *list) { node_t *current = NULL; if (list->head == NULL) { list->head = createnode(room); } else { current = list->head; while (current->next != NULL) { current = current->next; } current->next = createnode(room); } }
结构体定义
typedef struct List { struct Node *head; } list; typedef struct Node { const struct Room *data; struct Node *next; } node_t; typedef struct Room { unsigned int index; color_t color; list objects; char *description; /* the description buffer that will be written from the file */ } room_t;
错误原因分析与修复方案
1. 字符串内存分配越界(最可能触发当前错误)
new_room->description = (char *)malloc(strlen(description));中,strlen仅返回字符串长度,不包含终止符\0,strcpy会将\0写入到分配内存的外部,破坏堆内存结构,后续操作链表时触发SIGSEGV。
修复:
// 分配内存时多留1字节存储'\0' new_room->description = (char *)malloc(strlen(description) + 1); // 增加内存分配失败的检查 if (new_room->description == NULL) { fprintf(stderr, "Failed to allocate memory for description\n"); free(new_room); return; } strcpy(new_room->description, description);
2. List结构体未初始化
如果传入add_to_list的list是野指针,或者list->head未初始化为NULL,会导致访问非法内存。
修复:
使用list前必须初始化:
// 栈上初始化 list room_list; room_list.head = NULL; // 动态分配时初始化 list *room_list = malloc(sizeof(list)); if (room_list != NULL) { room_list->head = NULL; }
3. Createnode返回NULL未处理
当malloc失败时createnode返回NULL,若直接将NULL赋值给list->head或current->next,后续遍历链表会触发空指针访问。
修复:
在add_to_list中检查createnode返回值:
void add_to_list (const room_t *room, list *list) { node_t *current = NULL; node_t *new_node = createnode(room); if (new_node == NULL) { fprintf(stderr, "Failed to create new node\n"); return; } if (list->head == NULL) { list->head = new_node; } else { current = list->head; while (current->next != NULL) { current = current->next; } current->next = new_node; } }
4. Room结构体中子链表未初始化
room_t中的objects是list类型,未初始化的话其head成员是野指针,可能间接破坏内存。
修复:
在malloc得到new_room后,初始化子链表:
room_t *new_room = (room_t *)malloc(sizeof(room_t)); if (new_room == NULL) { fprintf(stderr, "Failed to allocate room\n"); return; } new_room->index = index; new_room->color = color; new_room->objects.head = NULL; // 初始化子链表head
内容的提问来源于stack exchange,提问作者weuoimi
相关产品推荐
相关产品推荐

