C: Ошибка сегментации в pthread_create - PullRequest
3 голосов
/ 24 ноября 2011

Я получаю ошибку Segmentation Fault при запуске моей программы в GCC. Это довольно длинная программа, поэтому я публикую только те части, которые, на мой взгляд, актуальны; пожалуйста, дайте мне знать, если требуется больше.

void *RelaxThread(void *para) {
    printf("Entering RelaxThread...\n");
    struct Parameter *parameters;
    parameters = (struct Parameter *) para;
    /*Some code here*/
    pthread_exit(NULL);
}

int relax(double **matrix, int size, int threads, double precision) {
    keepRunning = 0;
    int rowAllocation = (size-2) / threads;     
    struct Parameter para[threads];
    pthread_t threadcount[threads];
    int current;
    int startRow = 1;
    long t;    
    for(t=0; t<threads; t++){       
        para[t].matrix = matrix;
        para[t].size = size;
        para[t].threads = threads;
        para[t].precision = precision;
        para[t].allocation = rowAllocation;
        para[t].threadId = t;
        para[t].startRow = startRow;
        startRow += rowAllocation;
        printf("DebugMsg1\n");
        current = pthread_create(&threadcount[t], NULL, RelaxThread, (void *) &para[t]);
        printf("DebugMsg2\n");
    }
    void *status;
    int rc;
    for(t=0; t<threads; t++) {
        rc = pthread_join(threadcount[t], &status);
        if (rc) {
            exit(-1);
        }
    }
    if (keepRunning) {
        printf("Iterating...\n");
        relax(matrix, size, threads, precision); 
    }
}

int main(int argc, char *argv[])
{
    int const size = 8;
    int const threads = 2;
    double const precision = 1e-6;
    double **matrix = (double **) malloc(size * sizeof(double));
    populateMatrix(matrix, size);
    relax(matrix, size, threads, precision);
    free(matrix);
    pthread_exit(NULL);
    return 0;
}

Код работает нормально, если размер установлен на 8 или ниже. Однако все, что больше этого (пока он поддерживает только четные числа), вызывает ошибку сегментации на второй итерации relax (). Поэтому сообщения отладки запускаются как:

Debug1
Debug2
Debug1
Debug2
Entering RelaxThread...
Entering RelaxThread...
Iterating...
Debug1
Debug2
Debug1
Segmentation Fault

Тот факт, что это происходит, когда размер равен 8 или меньше, но падает выше этого числа, полностью смутил меня, и я потратил много времени, пытаясь понять, почему это происходит. Я полностью признаю, что мой код не является ни самым лучшим, ни самым эффективным, но был бы очень признателен за некоторые советы относительно того, почему это не помогает.

Редактировать 1: присоединение журнала запросов GDB по запросу.

Debug1
[New Thread 0x40040940 (LWP 23270)]
Debug2
Debug1
Entering RelaxThread...
Entering RelaxThread 0
[New Thread 0x40081940 (LWP 23271)]
Debug2
Entering RelaxThread...
Entering RelaxThread 1
[Thread 0x40040940 (LWP 23270) exited]
Main: completed join with thread 0 having a status of 0
Main: completed join with thread 1 having a status of 0
Iterating...
Debug1
[Thread 0x40081940 (LWP 23271) exited]
[New Thread 0x40081940 (LWP 23272)]
Debug2
Debug1

Edit2: обновлен журнал обратной трассировки после изменений.

Edit3: ниже приведен полный текст RelaxThread

    void *RelaxThread(void *para) {
        struct Parameter *parameters;
        parameters = (struct Parameter *) para;
        double **matrix = parameters->matrix;
        int size = parameters->size;
        double precision = parameters->precision;
        int threads = parameters->threads;
        int threadId = parameters->threadId;
        int startRow = parameters->startRow;
        int allocation = parameters->allocation;
        int finishRow = (startRow + allocation);
        int i;
        int j;
        double oldValue;
        double newValue;
        double difference;
        for(i=startRow;i<finishRow;i++) {
            for (j=1;j<size-1;j++) {
                pthread_mutex_lock (&mutexmatrix); //Tested with and without the mutex, which is globally defined and initialised elsewhere
                oldValue = matrix[i][j];
                newValue = ((matrix[i+1][j] + matrix[i-1][j] + matrix[i][j+1] + matrix[i][j-1]) / 4);
                matrix[i][j] = newValue;
                pthread_mutex_unlock (&mutexmatrix);
                difference = oldValue - newValue;
                if(difference < 0) {
                    difference = -difference; 
                }
                //printf("Precision on thread%d: %f , aiming for %f\n",threadId, difference,precision);
                if (difference > precision) {
                    keepRunning = 1;
                }
            }
        }
}

1 Ответ

3 голосов
/ 24 ноября 2011

Правильная инициализация, при условии, что матрица в квадрате будет:

double **matrix = malloc(size * sizeof(double *));
for(int i=0; i<size; i++)
{
    matrix[i] = malloc(size * sizeof(double));
    for(int j=0; j<size; j++)
    {
        matrix[i][j] = 0; // removing the junk contents
    }
}

РЕДАКТИРОВАТЬ: Я также понял, что вы на самом деле никогда не инициализировать void *status.Поскольку вы не используете его, измените его на rc = pthread_join(threadcount[t], NULL);, это, безусловно, еще одна проблема.

EDIT3: Еще одна проблема, которую я обнаружил, - int startRow = 1;, я не вижу, как вы получаете доступ к матрице, ноего индекс должен начинаться с 0.

EDIT4: Кроме того, когда вы освобождаете двумерный массив, вам нужно сделать это следующим образом:

for(int i=0; i<size; i++)
{
    free(matrix[i]);    //Free each row pointer
}
free(matrix);
...