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

C语言服务端客户端程序出队操作触发Segmentation Fault问题排查

队列出队触发Segmentation Fault问题排查与解决

开发服务端-客户端程序时,客户端collector负责将数据包入队,sender负责出队,但执行出队操作时频繁触发Segmentation Fault错误。

队列实现代码

aqueue *init_aqueue(void)
{
    aqueue *q;

    q = malloc(sizeof(aqueue));
    q->head = NULL;
    q->tail = NULL;

    return (q);
}

aqueue_node  *init_node(packet *data, aqueue_node *tail)
{
    aqueue_node  *new;

    new = malloc(sizeof(aqueue_node));
    new->data = data;
    new->prev = tail;
    new->next = NULL;
}

packet   *peek(aqueue *q)
{
    packet  *res;

    if (!q->size)
        return (NULL);
    else
    {
        res = malloc(sizeof(packet));
        res->length = q->head->data->length;
        res->payload = strndup(q->head->data->payload, res->length);
    }
        return (res);
}

void    enqueue (aqueue *q, packet *data)
{
    aqueue_node *new;

    new = init_node(data, q->tail);
    if (q->head == NULL) //adding first node of aqueue
    {
        q->head = new;
        q->size = 1;
    }
    else
    {
        q->tail->next = new;
        q->size += 1;
    }
    q->tail = new;
}

packet  *dequeue(aqueue *q)
{
    packet      *data;
    aqueue_node *temp;

    if (q->size == 0)
    {
        return (NULL);
    }
    else
    {
        if (q->head == q->tail)
        {
            //When aqueue contains only one node
            free(q->head->data);
            free(q->head);
            q->tail = NULL;
            q->head = NULL;
        }
        else
        {
            data = peek(q);
            temp = q->head;
            q->head = q->head->next;
            q->head->prev = NULL;
            free(temp->data);
            free(temp);
        }
        q->size--;
        return (data);
    }
}

共享资源与线程代码

队列共享定义(agent.c)

aqueue * queue;

Collector入队代码

//send four packet
pthread_mutex_lock(&p->aqueue_lock);
        enqueue(q, get_mem_info());
        enqueue(q, get_net_info());
        enqueue(q, get_cpu_info());
        enqueue(q, get_proc_info());

Sender出队代码

packet  *data;

data = NULL;
if (q->size > 0)
{
    data = dequeue(q);
}
if (data)
{
    if (0 > send(clientfd, data->payload, data->length, 0))
    {
        perror("send error");
        exit (EXIT_FAILURE);
    }
}

lldb调试结果

* thread #2, name = 'agent', stop reason = signal SIGSEGV: invalid address (fault address: 0x50e8)
    frame #0: 0x0000aaaaaaaa3c64 agent`dequeue(q=0x0000aaaaaaab62e0) at agent_queue.c:85:18
   82           {
   83               cur = q->head;
   84               q->head = q->head->next;
-> 85               q->head->prev = NULL;
   86               free(cur->data);
   87               free(cur);
   88           }

尝试的修改

  • 修复init_node函数,添加返回值:
aqueue_node  *init_node(packet *data, aqueue_node *tail)
{
    aqueue_node  *new;

    new = malloc(sizeof(aqueue_node));
    new->data = data;
    new->prev = tail;
    new->next = NULL;
    return (new); //added
}

修改后错误仍存在。

  • 修改dequeue函数变量名,明确返回复制的数据:
packet  *dequeue(aqueue *q)
{
    packet      *copied_data;
    aqueue_node *temp;

    printf("queue size : %d\n", q->size);
    if (q->size == 0)
    {
        return (NULL);
    }
    else
    {
        if (q->head == q->tail)
        {
            //When aqueue contains only one node
            free(q->head->data);
            free(q->head);
            q->tail = NULL;
            q->head = NULL;
        }
        else
        {
            copied_data = peek(q);
            temp = q->head;
            q->head = q->head->next;
            q->head->prev = NULL;
            free(temp->data);
            free(temp);
        }
        q->size--;
        return (copied_data);
    }
}
  • 修复enqueue函数中prev指针赋值:
void    enqueue (aqueue *q, packet *data)
{
    aqueue_node *new;

    new = init_node(data, q->tail);
    if (q->head == NULL) //adding first node of aqueue
    {
        q->head = new;
        q->size = 1;
    }
    else
    {
        q->tail->next = new;
        new->prev = q->tail; //added
        q->size += 1;
    }
    q->tail = new;
}

最终原因与解决

经过排查,发现问题源于调试阶段添加了释放整个队列的代码,但后续忘记删除,导致出队操作时访问了已经被释放的内存区域,触发Segmentation Fault。移除残留的队列释放代码后,问题解决。

内容的提问来源于stack exchange,提问作者acho

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 13:51:48