Ошибка сегментации (дамп ядра) в C — при использовании PTHREADS

Здравствуйте, ребята, У меня есть проблема в моем коде, и я не знаю, как ее исправить (ошибка сегментации (сброс ядра))!

Итак, мой учитель хочет, чтобы я написал программу, которая создает N ступеней и заставляет их выполнять некоторые вычисления. У меня есть 3 глобальных массива 2d A, B, C (у меня они как указатели, потому что я не знаю размер, пользователь дает его как аргумент). Я пытаюсь выделить им память в основной функции.

Итак, проблема в том, что я получаю ошибку сегментации, когда пытаюсь создать протекторы в "pthread_create(&tid[id],NULL,add,(void *)(long) i);" :(. Я не могу понять, почему это происходит. Я пытался использовать команду gdb, но в результате проблема заключалась в pthread_create.

Однако, когда я добавляю в комментарий массивы (A, B, C) и используемый ими malloc, он запускается (но окончательный результат равен 0).

Я использую виртуальную коробку (с Ubuntu внутри, если это поможет: D).

Следующий код - это то, что я написал до сих пор:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>

long int p,N,Total_Sum;
long int **A,**B,**C;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_barrier_t bar;

void * add(void *arg){

    long int i,j,Local_Sum=0;
    long int lines,start,end,id;

    id = (long int)arg;
    lines = N/p;
    start = id*lines;
    end = start+lines;

    for(i=start;i<end;i++){
        for(j=0;j<N;j++){
            A[i][j] = 1;
            B[i][j] = 1;
        }
    }
    for(i=start;i<end;i++){
        for(j=0;j<N;j++){
            C[i][j] = A[i][j] * B[i][j];
            Local_Sum += C[i][j];
            printf("C[%ld][%ld] = %ld\n",i,j,C[i][j]);
        }
    }
    pthread_mutex_lock(&mutex);
    Total_Sum += Local_Sum;
    pthread_mutex_unlock(&mutex);
    pthread_barrier_wait(&bar);
    pthread_exit(0);
}

int main(int argc, char *argv[]){

    long int i,j,id;
    pthread_t *tid;
    if(argc!=3){
        printf("Provide Number Of Threads And Size\n");
        exit(1);
    }
    p = atoi(argv[1]);
    tid = (pthread_t *) malloc(p*sizeof(pthread_t));
    if(tid == NULL){
        printf("Could Not Allocate Memory\n");
        exit(1);
    }

    pthread_barrier_init(&bar,NULL,p);

    N = atoi(argv[2]);
    A = (long int**) malloc(N*sizeof(long int*));
    B = (long int**) malloc(N*sizeof(long int*));
    C = (long int**) malloc(N*sizeof(long int*));

    for(i=0;i<N;i++){
        A[i] = (long int*) malloc(N*sizeof(long int));
        B[i] = (long int*) malloc(N*sizeof(long int));
        C[i] = (long int*) malloc(N*sizeof(long int));
    }

    if((A==NULL) || (B == NULL) || (C == NULL)){
        printf("Count Not Allocate Memory\n");
        exit(1);
    }

    for(i=0;i<p;i++){
        pthread_create(&tid[id],NULL,add,(void *)(long) i);
    }
    for(i=0;i<p;i++){
        pthread_join(tid[id],NULL);
    }

    for(i=0;i<N;i++){
        free(A[i]);
        free(B[i]);
        free(C[i]);
    }
    free(A);
    free(B);
    free(C);

    printf("Final Result Is Equal To: %ld\n",Total_Sum);

    return 0;
}

****** Я знаю, что это становится немного запутанным из-за мьютекса и барьеров, но спросите меня о дополнительных спецификациях: D. ******

Спасибо!!!!!!!!


person george nikitas    schedule 23.05.2018    source источник
comment
Скомпилируйте со всеми предупреждениями и отладочной информацией: gcc -Wall -Wextra -g с помощью GCC. Улучшите свой код, чтобы не было предупреждений. используйте gdb отладчик, а также valgrind, чтобы понять поведение вашей программы   -  person Basile Starynkevitch    schedule 23.05.2018


Ответы (2)


Я думаю, что единственная проблема - это индексы в следующих строках:

for(i=0;i<p;i++){
    pthread_create(&tid[id],NULL,add,(void *)(long) i);
}
for(i=0;i<p;i++){
    pthread_join(tid[id],NULL);
}

id был только объявлен, но никогда не инициализировался! Возможно, это просто опечатка, и вы хотели использовать i в качестве индекса для tid.

Решения должны быть:

for(i=0;i<p;i++){
    pthread_create(&tid[i],NULL,add,(void *)(long) i);
}
for(i=0;i<p;i++){
    pthread_join(tid[i],NULL);
}
person Alexander Pane    schedule 23.05.2018
comment
Вау я этого не видел о_О!!! Я почему-то искал более сложные решения. СПАСИБО!!! - person george nikitas; 23.05.2018
comment
@georgenikitas Нет проблем! Я знаю, что чувство неработающего кода только из-за опечаток так расстраивает :) В любом случае, если это была единственная проблема, вы можете принять ответ и закрыть его. - person Alexander Pane; 23.05.2018

Ответ на источник вашей проблемы с дампом ядра уже был рассмотрен, но для решения других вопросов, которые вы задали или заявили:

1-й:
Относительно вашего утверждения: у меня они как указатели, потому что я не знаю размер, пользователь дает его в качестве аргумента.

Часто в C вы можете избежать использования calloc/malloc в своем коде, используя вместо этого VLA. Доступно в версии C99 и выше. (см. ссылки)
VLA
VLA b

2-е:
Относительно вашего заявления: Я знаю, что оно становится немного запутанным...
На самом деле это не это запутанность, но вы можете подумать об очистке шагов выделения/освобождения памяти, переместив большую часть работы в функцию:

long int **A,**B,**C;
int N;
... 
//in main
N = atoi(argv[2]); 
A = Create2D(N, N);
B = Create2D(N, N);
B = Create2D(N, N);
...
free2D(A, N);
free2D(B, N);
free2D(C, N);


long ** Create2D(int c, int r)
{   
    long **arr;
    int    y = 0;

    arr   = calloc(c, sizeof(long *));
    for(y=0;y<c;y++)
    {
        arr[y] = calloc((2*y)+1, sizeof(long)); 
    }
    return arr;
}

void free2D(long **arr, int c)
{
    int i;
    if(!arr) return;
    for(i=0;i<c;i++)
    {
        if(arr[i]) 
        {
            free(arr[i]);
            arr[i] = NULL;
        }
    }
    free(arr);
    arr = NULL;
}

Дополнительное примечание:
нет ничего абсолютно неправильного в ваших операторах памяти, как они есть:

A = (long int**) malloc(N*sizeof(long int*));  

Однако, хотя C++ требует этого, нет причин приводить возврат malloc , calloc или realloc при использовании C. (См. обсуждение здесь) Достаточно следующего (на C):

A = malloc(N*sizeof(long int*));
person ryyker    schedule 23.05.2018