You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修复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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 03:29:54