POSIX 线程。为什么生产者消费者程序终止了?
POSIX Thread. Why is the producer-consumer program terminated?
我尝试使用 POSIX Thread(一个用于处理线程的库)编写一个简单的 C 生产者-消费者程序。
代码有一个全局队列,线程从中交换信息。该队列已经过测试,应该可以正常工作。还涉及到两个线程:
制片人。生成一个随机数并将其放入队列中;
消费者。从队列中检索一个数字并将其打印到屏幕上。
main.c
:
#include <stdio.h>
#include <pthread.h>
#include <time.h>
#include "queue.h"
pthread_mutex_t mutex;
pthread_cond_t pcond;
pthread_cond_t ccond;
static const unsigned int X = 10;
void* producer(void* args)
{
for (int i = 0; i < X; i++)
{
pthread_mutex_lock(&mutex);
while (queue_is_full())
pthread_cond_wait(&pcond, &mutex);
if (queue_is_empty())
pthread_cond_signal(&ccond);
queue_enqueue(rand() % (9999 + 1 - 0) + 0);
pthread_mutex_unlock(&mutex);
}
return NULL;
}
void* consumer(void* args)
{
for (int i = 0; i < X; i++)
{
pthread_mutex_lock(&mutex);
while (queue_is_empty())
pthread_cond_wait(&ccond, &mutex);
if (queue_is_full())
pthread_cond_signal(&pcond);
printf("%i", queue_dequeue());
pthread_mutex_unlock(&mutex);
}
return NULL;
}
int main(void)
{
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&pcond, NULL);
pthread_cond_init(&ccond, NULL);
pthread_t thProducer, thConsumer;
pthread_create(&thProducer, NULL, producer, NULL);
pthread_create(&thConsumer, NULL, consumer, NULL);
pthread_join(thProducer, NULL);
pthread_join(thConsumer, NULL);
return 0;
}
该程序在启动时终止。消息 Application.exe has stopped working.
是系统在启动程序后立即发出的。我该如何修复程序?
queue.c
:
#include "queue.h"
#define CAPACITY 2048
static int* queue;
static int head;
static int tail;
void queue_init()
{
queue = malloc(CAPACITY * sizeof(int));
head = -1;
tail = 0;
}
void queue_enqueue(int value)
{
if (queue_is_full())
exit(1);
queue[tail] = value;
if (head == -1)
head = 0;
if (tail == CAPACITY - 1)
tail = 0;
else
tail++;
}
int queue_dequeue()
{
if (queue_is_empty())
exit(1);
int item = queue[head];
if (head != CAPACITY - 1)
head++;
else
head = 0;
if (head == tail)
{
head = -1;
tail = 0;
}
return item;
}
bool queue_is_full()
{
return head == tail;
}
bool queue_is_empty()
{
return head == -1;
}
int queue_size()
{
if (head != -1)
{
return head < tail ? tail - head : (CAPACITY - head) + tail;
}
return 0;
}
gcc 的 -fsanitize=address
找到了直接问题 immediately(每个调试器也应该如此)。
AddressSanitizer:DEADLYSIGNAL
=================================================================
==1==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x000000401436 bp 0x7fbd0f7fde40 sp 0x7fbd0f7fde30 T2)
==1==The signal is caused by a READ memory access.
==1==Hint: address points to the zero page.
#0 0x401436 in queue_dequeue /app/example.c:56
#1 0x401596 in consumer /app/example.c:99
#2 0x7fbd139c4608 in start_thread (/lib/x86_64-linux-gnu/libpthread.so.0+0x8608)
#3 0x7fbd138e9162 in __clone (/lib/x86_64-linux-gnu/libc.so.6+0x11f162)
所以这是一个 NULL
指针取消引用在这一行:
int item = queue[head];
queue
由 queue_init
初始化...从未调用过。
我尝试使用 POSIX Thread(一个用于处理线程的库)编写一个简单的 C 生产者-消费者程序。
代码有一个全局队列,线程从中交换信息。该队列已经过测试,应该可以正常工作。还涉及到两个线程:
制片人。生成一个随机数并将其放入队列中; 消费者。从队列中检索一个数字并将其打印到屏幕上。
main.c
:
#include <stdio.h>
#include <pthread.h>
#include <time.h>
#include "queue.h"
pthread_mutex_t mutex;
pthread_cond_t pcond;
pthread_cond_t ccond;
static const unsigned int X = 10;
void* producer(void* args)
{
for (int i = 0; i < X; i++)
{
pthread_mutex_lock(&mutex);
while (queue_is_full())
pthread_cond_wait(&pcond, &mutex);
if (queue_is_empty())
pthread_cond_signal(&ccond);
queue_enqueue(rand() % (9999 + 1 - 0) + 0);
pthread_mutex_unlock(&mutex);
}
return NULL;
}
void* consumer(void* args)
{
for (int i = 0; i < X; i++)
{
pthread_mutex_lock(&mutex);
while (queue_is_empty())
pthread_cond_wait(&ccond, &mutex);
if (queue_is_full())
pthread_cond_signal(&pcond);
printf("%i", queue_dequeue());
pthread_mutex_unlock(&mutex);
}
return NULL;
}
int main(void)
{
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&pcond, NULL);
pthread_cond_init(&ccond, NULL);
pthread_t thProducer, thConsumer;
pthread_create(&thProducer, NULL, producer, NULL);
pthread_create(&thConsumer, NULL, consumer, NULL);
pthread_join(thProducer, NULL);
pthread_join(thConsumer, NULL);
return 0;
}
该程序在启动时终止。消息 Application.exe has stopped working.
是系统在启动程序后立即发出的。我该如何修复程序?
queue.c
:
#include "queue.h"
#define CAPACITY 2048
static int* queue;
static int head;
static int tail;
void queue_init()
{
queue = malloc(CAPACITY * sizeof(int));
head = -1;
tail = 0;
}
void queue_enqueue(int value)
{
if (queue_is_full())
exit(1);
queue[tail] = value;
if (head == -1)
head = 0;
if (tail == CAPACITY - 1)
tail = 0;
else
tail++;
}
int queue_dequeue()
{
if (queue_is_empty())
exit(1);
int item = queue[head];
if (head != CAPACITY - 1)
head++;
else
head = 0;
if (head == tail)
{
head = -1;
tail = 0;
}
return item;
}
bool queue_is_full()
{
return head == tail;
}
bool queue_is_empty()
{
return head == -1;
}
int queue_size()
{
if (head != -1)
{
return head < tail ? tail - head : (CAPACITY - head) + tail;
}
return 0;
}
gcc 的 -fsanitize=address
找到了直接问题 immediately(每个调试器也应该如此)。
AddressSanitizer:DEADLYSIGNAL
=================================================================
==1==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x000000401436 bp 0x7fbd0f7fde40 sp 0x7fbd0f7fde30 T2)
==1==The signal is caused by a READ memory access.
==1==Hint: address points to the zero page.
#0 0x401436 in queue_dequeue /app/example.c:56
#1 0x401596 in consumer /app/example.c:99
#2 0x7fbd139c4608 in start_thread (/lib/x86_64-linux-gnu/libpthread.so.0+0x8608)
#3 0x7fbd138e9162 in __clone (/lib/x86_64-linux-gnu/libc.so.6+0x11f162)
所以这是一个 NULL
指针取消引用在这一行:
int item = queue[head];
queue
由 queue_init
初始化...从未调用过。