簡體   English   中英

在 C 中創建多個線程時出現分段錯誤

[英]Segmentation fault while creating multiple threads in C

我正在嘗試創建 1000000 多個線程並讓它們從隊列中添加和刪除元素。 隊列的大小為 10 個元素,當它已滿並想要添加一個元素時,它會等待來自 Condition 的信號,當它為空並試圖刪除一個元素時也是如此。

當我創建 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(&notFull, &lock);
    EnQueue(&list, number);
    pthread_cond_signal(&notEmpty);
    sum++;
    pthread_mutex_unlock(&lock);
    pthread_exit(0);
}

void *deleteFromList()
{
    pthread_mutex_lock(&lock);
    while(isEmptyQueue(list))
        pthread_cond_wait(&notEmpty, &lock);
    DeQueue(&list);
    pthread_cond_signal(&notFull);
    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];

具有自動存儲持續時間的數組(通常稱為“局部變量”)通常存儲在稱為堆棧的固定大小 memory 塊中的系統上。 如果數組的大小超過了堆棧的大小,就會發生堆棧溢出,您的程序將無法運行。

在我的系統上 1.000.000 pthread_t是 8.000.000 字節,高於我系統的(默認)堆棧大小。 所以這樣的程序在我的系統上會失敗。

你可以做(至少)三件事:

  1. 將數組變量放在全局空間中(一種丑陋的解決方案)

  2. 使用malloc分配陣列

  3. 如果系統允許,增加堆棧大小

對於解決方案 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,我會使用 go。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM