在 C 中创建多个线程时出现分段错误
Segmentation fault while creating multiple threads in C
我正在尝试创建 1000000 多个线程并让它们在队列中添加和删除元素。
队列的大小为 10 个元素,当它已满并想要添加一个元素时,它会等待来自条件的信号,当它为空并尝试删除一个元素时,情况也是如此。
当我创建 100000 个线程时,代码工作正常,但当我尝试添加一个或多个零时,代码出现分段错误。
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#define SIZE 10
long NBTHREADS = 1000000;
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t notFull = PTHREAD_COND_INITIALIZER;
pthread_cond_t notEmpty = PTHREAD_COND_INITIALIZER;
long sum = 0;
typedef long element;
typedef struct queue{
element data[SIZE];
int front, rear;
}queue;
queue CreateQueue(){
queue q;
q.front = 1;
q.rear = 0;
return q;
}
queue list;
int isEmptyQueue(queue q) {
return (q.front == (q.rear + 1) % SIZE);
}
int isFullQueue(queue q) {
return (q.front == (q.rear + 2) % SIZE);
}
int EnQueue(queue *q,element e) {
q->rear = (q->rear + 1) % SIZE;
q->data[q->rear] = e;
return 1;
}
int DeQueue(queue *q) {
q->front = (q->front + 1) % SIZE;
return 1;
}
int Front(queue q,element *e) {
if (isEmptyQueue(q))return 0;
*e = q.data[q.front];
return 1;
}
void PrintQueue(queue q){
element e;
while(!isEmptyQueue(q) && Front(q, &e)){
printf("%ld ", e);
DeQueue(&q);
}
printf("\n");
}
void *addToList(void *num)
{
long number = (long)num;
pthread_mutex_lock(&lock);
while(isFullQueue(list))
pthread_cond_wait(¬Full, &lock);
EnQueue(&list, number);
pthread_cond_signal(¬Empty);
sum++;
pthread_mutex_unlock(&lock);
pthread_exit(0);
}
void *deleteFromList()
{
pthread_mutex_lock(&lock);
while(isEmptyQueue(list))
pthread_cond_wait(¬Empty, &lock);
DeQueue(&list);
pthread_cond_signal(¬Full);
sum++;
pthread_mutex_unlock(&lock);
pthread_exit(0);
}
int main()
{
list = CreateQueue();
void *status;
pthread_attr_t attr;
pthread_t threads[NBTHREADS];
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
for(long i=0; i<NBTHREADS; i++)
{
long err;
if(i<(NBTHREADS/2))
{
err = pthread_create(&threads[i], &attr, addToList, (void*)i);
}else{
err = pthread_create(&threads[i], &attr, deleteFromList, NULL);
}
if(err){
printf("\nError Creating Thread...");
exit(-1);
}
}
pthread_attr_destroy(&attr);
for(long i=0; i<NBTHREADS; i++)
{
long err = pthread_join(threads[i], &status);
if(err)
printf("\nFAILED TO JOIN MAIN WITH THREAD %ld", (long)status);
else
printf("\nsuccessfully joined");
}
printf("\nSum is: %ld", sum);
PrintQueue(list);
pthread_exit(NULL);
}
它给我这个错误:
Process returned -1073741571 (0xC00000FD) execution time : 9.364 s
我对多线程和并行编程还是个新手。
也许我在错误的地方使用了锁?
但问题是,当我将 NBTHREADS 变量设置为 100000 或更少时,程序执行正常并返回 0,并且队列不打印任何内容(它是空的)。
我不知道我的问题出在哪里,感谢帮助。
可能存在阻止 1.000.000 个线程的其他系统限制,但(很可能)涉及堆栈溢出问题。
在 main
你有:
pthread_t threads[NBTHREADS];
具有自动存储持续时间的数组(通常称为“局部变量”)通常在系统上存储在称为堆栈的固定大小的内存块中。如果数组的大小超过堆栈的大小,就会出现堆栈溢出,程序将无法运行。
在我的系统上 1.000.000 pthread_t
是 8.000.000 字节,高于我系统的(默认)堆栈大小。所以这样的程序在我的系统上会失败。
你可以(至少)做 3 件事:
将数组变量放入全局 space(有点难看的解决方案)
使用malloc
分配数组
如果您的系统允许,请增加堆栈大小
对于解决方案 1,执行:
//long NBTHREADS = 1000000;
#define NBTHREADS 1000000
pthread_t threads_global[NBTHREADS];
int main()
{
list = CreateQueue();
void *status;
pthread_attr_t attr;
////pthread_t threads[NBTHREADS];
pthread_attr_init(&attr);
并更新代码以使用这个新的“丑陋”变量名
对于解决方案 2,执行:
int main()
{
list = CreateQueue();
void *status;
pthread_attr_t attr;
pthread_t *threads = malloc(NBTHREADS * sizeof *threads);
assert(threads != NULL); // Or: if (threads == NULL) exit(1);
对于解决方案 3:
取决于您的系统
我会选择解决方案 2。
我正在尝试创建 1000000 多个线程并让它们在队列中添加和删除元素。 队列的大小为 10 个元素,当它已满并想要添加一个元素时,它会等待来自条件的信号,当它为空并尝试删除一个元素时,情况也是如此。
当我创建 100000 个线程时,代码工作正常,但当我尝试添加一个或多个零时,代码出现分段错误。
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#define SIZE 10
long NBTHREADS = 1000000;
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t notFull = PTHREAD_COND_INITIALIZER;
pthread_cond_t notEmpty = PTHREAD_COND_INITIALIZER;
long sum = 0;
typedef long element;
typedef struct queue{
element data[SIZE];
int front, rear;
}queue;
queue CreateQueue(){
queue q;
q.front = 1;
q.rear = 0;
return q;
}
queue list;
int isEmptyQueue(queue q) {
return (q.front == (q.rear + 1) % SIZE);
}
int isFullQueue(queue q) {
return (q.front == (q.rear + 2) % SIZE);
}
int EnQueue(queue *q,element e) {
q->rear = (q->rear + 1) % SIZE;
q->data[q->rear] = e;
return 1;
}
int DeQueue(queue *q) {
q->front = (q->front + 1) % SIZE;
return 1;
}
int Front(queue q,element *e) {
if (isEmptyQueue(q))return 0;
*e = q.data[q.front];
return 1;
}
void PrintQueue(queue q){
element e;
while(!isEmptyQueue(q) && Front(q, &e)){
printf("%ld ", e);
DeQueue(&q);
}
printf("\n");
}
void *addToList(void *num)
{
long number = (long)num;
pthread_mutex_lock(&lock);
while(isFullQueue(list))
pthread_cond_wait(¬Full, &lock);
EnQueue(&list, number);
pthread_cond_signal(¬Empty);
sum++;
pthread_mutex_unlock(&lock);
pthread_exit(0);
}
void *deleteFromList()
{
pthread_mutex_lock(&lock);
while(isEmptyQueue(list))
pthread_cond_wait(¬Empty, &lock);
DeQueue(&list);
pthread_cond_signal(¬Full);
sum++;
pthread_mutex_unlock(&lock);
pthread_exit(0);
}
int main()
{
list = CreateQueue();
void *status;
pthread_attr_t attr;
pthread_t threads[NBTHREADS];
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
for(long i=0; i<NBTHREADS; i++)
{
long err;
if(i<(NBTHREADS/2))
{
err = pthread_create(&threads[i], &attr, addToList, (void*)i);
}else{
err = pthread_create(&threads[i], &attr, deleteFromList, NULL);
}
if(err){
printf("\nError Creating Thread...");
exit(-1);
}
}
pthread_attr_destroy(&attr);
for(long i=0; i<NBTHREADS; i++)
{
long err = pthread_join(threads[i], &status);
if(err)
printf("\nFAILED TO JOIN MAIN WITH THREAD %ld", (long)status);
else
printf("\nsuccessfully joined");
}
printf("\nSum is: %ld", sum);
PrintQueue(list);
pthread_exit(NULL);
}
它给我这个错误:
Process returned -1073741571 (0xC00000FD) execution time : 9.364 s
我对多线程和并行编程还是个新手。
也许我在错误的地方使用了锁?
但问题是,当我将 NBTHREADS 变量设置为 100000 或更少时,程序执行正常并返回 0,并且队列不打印任何内容(它是空的)。
我不知道我的问题出在哪里,感谢帮助。
可能存在阻止 1.000.000 个线程的其他系统限制,但(很可能)涉及堆栈溢出问题。
在 main
你有:
pthread_t threads[NBTHREADS];
具有自动存储持续时间的数组(通常称为“局部变量”)通常在系统上存储在称为堆栈的固定大小的内存块中。如果数组的大小超过堆栈的大小,就会出现堆栈溢出,程序将无法运行。
在我的系统上 1.000.000 pthread_t
是 8.000.000 字节,高于我系统的(默认)堆栈大小。所以这样的程序在我的系统上会失败。
你可以(至少)做 3 件事:
将数组变量放入全局 space(有点难看的解决方案)
使用
分配数组malloc
如果您的系统允许,请增加堆栈大小
对于解决方案 1,执行:
//long NBTHREADS = 1000000;
#define NBTHREADS 1000000
pthread_t threads_global[NBTHREADS];
int main()
{
list = CreateQueue();
void *status;
pthread_attr_t attr;
////pthread_t threads[NBTHREADS];
pthread_attr_init(&attr);
并更新代码以使用这个新的“丑陋”变量名
对于解决方案 2,执行:
int main()
{
list = CreateQueue();
void *status;
pthread_attr_t attr;
pthread_t *threads = malloc(NBTHREADS * sizeof *threads);
assert(threads != NULL); // Or: if (threads == NULL) exit(1);
对于解决方案 3:
取决于您的系统
我会选择解决方案 2。