我正在制作服务器客户端程序。
客户端的收集器需要将数据包数据排入队列,而发送方则需要将它们排成队列。
每当我试图将数据包出列时,都会出现分段错误。
以下是整个队列实现:
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;
收集器代码:
//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());
发件人代码:
packet *data;
data = NULL;
if (q->size > 0)
{
data = dequeue(q);
}
if (data)
{
if (0 > send(clientfd, data->payload, data->length,
{
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
}
但我还是犯了同样的错误。。
出队列的返回数据与出队列中释放的数据不同。我更改了变量名称以使其清楚:
packet *dequeue(aqueue *q)
{
packet *copied_data;
aqueue_node *temp;
printf("queue size : %dn", 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);
}
}
我发现我在入队函数中没有正确分配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;
}
编辑:
我在收集后释放了整个队列进行调试,但没能擦除它。这就是问题所在。抱歉混淆
启用并注意编译器的警告(我将-Wall -Wextra -pedantic
与gcc一起使用。(它会发现问题的。
init_node
不返回值。因此,您不是在向队列中添加节点,而是在添加垃圾。你的编译器会告诉你的。
在dequeue
中也有类似的问题,其中并非所有路径都在到达return data
之前设置data
。
此外,当您从dequeue
返回一个值时,它似乎是一个指向您释放的内存的指针!这不好。