Почему я получаю разные значения в режиме отладки? - PullRequest
2 голосов
/ 03 июня 2019

Моя программа должна рассчитывать произведение матрицы (умножение) из 2 заданных матриц с использованием многопоточности - каждый поток вычисляет один столбец.

Проблема в том, что при запуске из терминала у меня получается нескольконули столбцы.Я использовал отладчик, чтобы увидеть, где проблема - но на отладчике он работает каждый раз, когда все в порядке!Я не могу понять, где проблема

Как возможно, что я получаю разные значения при отладке по сравнению с обычным выполнением?

Я попробовал несколько "простых решений" из онлайн-поиска:


сброс виртуальной машины linux
сброс VSCode
, и я не получаю никаких ошибок или утечек памяти, но я не знаю, что делать дальше

мой код:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <errno.h>
#include <sys/stat.h>
#include <pthread.h>
int MATRIX_DIM=3;       //default
int **RESULT_MAT;

struct calcCol{
    int **matA;
    int **matB;
    int **matC;
    int dim;
    int i;
};

int ijMult(int **matA, int **matB,int dim, int i, int j);
void* colMatCalc(void* s);
void printMatrix(int **mat);
void getMatrix(int **mat);
void freeMatrices(int **matA, int **matB, int **matC);

void* printThreadId(void* arg){
    int i = *(int*)arg;
    printf("Thread id: %d \n", i);
    pthread_exit(NULL);
}

int main(){
    pthread_t tid[MATRIX_DIM];
    int args[MATRIX_DIM];
    pthread_attr_t attr;
    pthread_attr_init(&attr);

    printf("Enter enter MATRIX_DIM (number between 1 and 10) \n");
    scanf("%d",&MATRIX_DIM);
    if(MATRIX_DIM>10 || MATRIX_DIM<1)   
        MATRIX_DIM=3;   //default value

    //memory allocation for matrices
    int **matA = (int **)malloc(MATRIX_DIM * sizeof(int*));
    for(int i = 0; i < MATRIX_DIM; i++) matA[i] = (int *)malloc(MATRIX_DIM * sizeof(int));

    int **matB = (int **)malloc(MATRIX_DIM * sizeof(int*));
    for(int i = 0; i < MATRIX_DIM; i++) matB[i] = (int *)malloc(MATRIX_DIM * sizeof(int));

    RESULT_MAT = (int **)malloc(MATRIX_DIM * sizeof(int*));
    for(int i = 0; i < MATRIX_DIM; i++) RESULT_MAT[i] = (int *)malloc(MATRIX_DIM * sizeof(int));

    struct calcCol s;
        s.matA = matA;
        s.matB = matB;
        s.matC=RESULT_MAT;
        s.dim=MATRIX_DIM;
        s.i=0;

    printf("Enter elements of first matrix \n");
    getMatrix(matA);
    printf("Enter elements of second matrix \n");
    getMatrix(matB);

    for(int i=0 ; i<MATRIX_DIM ; i++)
    {
        args[i]=i;
        s.i=i;
        pthread_create(&tid[i], &attr, colMatCalc, &s);
    }

    for(int i=0 ; i<MATRIX_DIM ; i++)
    {
        if(pthread_join(tid[i], NULL)!=0)
        {
            perror("pthread_join faild.");
            exit(EXIT_FAILURE);
        }
        printf("Thread %d is terminated.\n", *(int*)(&args[i]));
    }
    printf("All threads are terminated!\n");

    printf("Product of the matrices: \n");
    printMatrix(RESULT_MAT);
    freeMatrices(matA, matB, RESULT_MAT);

    return 0;
}

//calculating (i,j) of the result matrix
int ijMult(int **matA, int **matB, int dim, int i, int j)
{
    int sum = 0;
    for(int k = 0 ; k < MATRIX_DIM ; k++)
        sum = sum + (matA[i][k]*matB[k][j]);
    return sum;
}

//calculating the 'i' column of the result matrix
void* colMatCalc(void* arg)
{
    struct calcCol s = *(struct calcCol*)arg;
    for(int k = 0 ; k < s.dim ; k++)
        s.matC[k][s.i] = ijMult(s.matA, s.matB,s.dim, k, s.i);
    return 0;
}

void printMatrix(int **mat)
{
    for(int i = 0 ; i < MATRIX_DIM ; i++)
    {
        for(int j = 0 ; j < MATRIX_DIM ; j++)
        {
            printf("%d \t", mat[i][j]);
        }
        printf("\n");
    }
}

void getMatrix(int **mat)
{
    for(int i=0 ; i<MATRIX_DIM ; i++)
    {
        for(int j=0 ; j<MATRIX_DIM ; j++)
        {
            scanf("%d",&mat[i][j]);
        }
    }
}

void freeMatrices(int **matA, int **matB, int **matC)
{
    for(int i=0 ; i < MATRIX_DIM ; i++)
    {
        free(matA[i]);
        free(matB[i]);
        free(RESULT_MAT[i]);
    }
    free(matA);
    free(matB);
    free(RESULT_MAT);
}

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

Ввод:
3
1 2 3
4 5 6
7 8 9

1 2 3
4 5 6
7 8 9

Ожидаемый результат
30 36 42
66 81 96

102 126 150

Фактический результат: то же, но вместо столбца нулей(каждый раз разные столбцы)
Спасибо.

1 Ответ

2 голосов
/ 03 июня 2019

Проблема с переменной s, которая является общей для всех потоков, то есть

s.i=i;

Когда вы обновляете s в цикле, каждый поток будет указывать на последнее содержимое s.


То, что вы можете сделать, это иметь разные экземпляры для каждого потока, как показано ниже.

for(int i=0 ; i<MATRIX_DIM ; i++)
{
   struct calcCol *s = malloc(sizeof(*s));
    s->matA = matA;
    s->matB = matB;
    s->matC=RESULT_MAT;
    s->dim=MATRIX_DIM;
    s->i=0;
    args[i]=i;
    s->i=i;
    pthread_create(&tid[i], &attr, colMatCalc, s);
}

При этом при обновлении содержимого *s это не повлияет на выполнение другого потока.

Убедитесь, что вы free завершили выполнение потока.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...