如何解决C 中的线程安全队列出现分段错误
我是 C 的新手,甚至对多线程和尝试创建线程安全队列数据结构的新手也是如此。在 dequeue() 中的第 116 行出现段错误错误(在代码中注释),我想知道是否有人可以看到我的实现有任何明显的问题。非常感谢
typedef struct node{
char *data;
struct node *next;
} node;
extern int directoryThreads;
//unbounded queue for file and directory queue
typedef struct {
node *head;;
node *tail;
int activeThreads;
int open;
int count;
pthread_mutex_t lock;
pthread_cond_t read_ready;
//pthread_cond_t write_ready;
} queue_t;
char *dequeue(queue_t *Q)
{
pthread_mutex_lock(&Q->lock); //lock queue
if(isempty(Q)){
Q->activeThreads--;
if(Q->activeThreads == 0){
pthread_mutex_unlock(&Q->lock);
return NULL;
}
while (isempty(Q) && Q->activeThreads>0) {
pthread_cond_wait(&Q->read_ready,&Q->lock);
}
if (isempty(Q)){
pthread_mutex_unlock(&Q->lock);
return NULL;
}
Q->activeThreads++;
}
//printf("%s","Dequeued: ");
//display(Q->head);
char *item = (char *) malloc(strlen(Q->head->data) + 1); //segault here
item = Q->head->data;
if(Q->count>1){
Q->head = Q->head->next;
}
else{
Q->head = NULL;
}
Q->count--;
pthread_mutex_unlock(&Q->lock);
return item;
}
解决方法
问题出在别处。 (我不排除导致竞争条件的信号协议问题,但我对此表示怀疑。稍后会详细介绍。)
如果信号由 Q->head->data
抛出,则 Q->head
包含垃圾,或者 isempty(Q)
和 Q->head != NULL
不一致。
如果信号由 strlen
抛出,Q->head->data
包含垃圾,或者字符串未正确以 NUL 结尾。
这并不意味着 dequeue
没有问题。
- 您无缘无故地在
dequeue
中分配内存。 - 更糟糕的是,您在下一行覆盖了
malloc
返回的指针,从而导致内存泄漏。 -
dequeue
永远不会改变Q->tail
,即使NULL
是Q->head
时它应该是NULL
。 - 信令协议过于复杂。
已修复:
// Call done() when nothing will be added to the queue anymore.
// This is done to unblock calls to dequeue,and
// to the cause future calls to return immediately.
void Queue_done(queue_t *Q) {
pthread_mutex_lock(&Q->lock);
Q->done = 1;
// In case another thread is blocked in dequeue().
pthread_cond_signal(&Q->read_ready);
pthread_mutex_unlock(&Q->lock);
}
char *Queue_dequeue(queue_t *Q) {
pthread_mutex_lock(&Q->lock);
while (!Q->head && !Q->done)
pthread_cond_wait(&Q->read_ready,&Q->lock);
char *rv;
if (Q->head) {
rv = Q->head->data;
Q->head = Q->head->next;
if (!Q->head)
Q->tail = NULL;
--Q->count;
} else {
// done() was called and queue is empty.
rv = NULL;
}
// In case another thread is blocked in dequeue().
pthread_cond_signal(&Q->read_ready);
pthread_mutex_unlock(&Q->lock);
return rv;
}
示例程序:
static queue_t Q;
void consumer(void) {
while (1) {
char *job = Queue_dequeue(&Q);
if (!job)
break;
// Do something with `job`.
free(job);
}
}
int main(void) {
Queue_init(&Q);
// Creates consumer threads here.
// Add stuff to queue here.
// -or-
// Create producer threads wait for them to complete here.
Queue_done(&Q);
// Wait for consumer threads to complete here.
Queue_destroy(&Q);
}
我之前 posted 有一个带演示的工作线程安全队列实现。 (不过,它使用固定大小的循环缓冲区而不是链表。)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。