pthread_create 调用的函数在将值分配给传递给它的结构时中断

Function called by pthread_create breaks when a value is assigned to the struct passed to it

我是 C 的新手。我有一个小程序,旨在使用 pthread 解决大型二维矩阵与其自身的点积问题。现在,当调用分配给 pthread 的函数并访问作为变量传递的结构时,程序会中断并停止工作。我真的不知道做错了什么。这是代码:

这是主要功能。

int main()
{
    int rc;
    int threadcount = 1;
    char filename[100];

    //patch to enable console printing in eclipse
    setvbuf(stdout, NULL, _IONBF, 0);

    do {
        prompt_for_fileName(filename);

        if (filename[0] == 'Q' || filename[0] == 'q') {
            puts("Program ended");
            return 0;
        }

        //read thread count
        read_threadcount(&threadcount);

        //initialize matrices
        matrix_def matrix = initialize_matrix(filename);

        //get the dimension of sub-matrices
        int dfRow = (int) floor(matrix.NROWS / threadcount);

        pthread_t threads[threadcount];
        pthread_arg pthreadargs[threadcount];
        for (int i = 0; i < threadcount; i++) {
            int startRow = i * dfRow;
            int endRow =
                    ((i + 1) == threadcount) ?
                            matrix.NROWS : (startRow + dfRow) - 1; //we're subtracting one because its zero based.

            //create a structure that we'll passed to the array.
            pthread_arg arg = { matrix.NROWS, matrix.NCOLS, startRow, endRow,
                    0.0, NULL, NULL };
            arg.data = matrix.data;
            arg.result_set = create_result_memory(matrix.NCOLS);

            fprintf(stderr, "before %p\n", arg.result_set);

            //push arg into array.
            pthreadargs[i] = arg;

            rc = pthread_create(&threads[i], NULL, compute_dot_product,
                    (void *) &arg);

            if (rc) {
                printf("ERROR; return code from pthread_create() is %d\n", rc);
                exit(-1);
            }
        }

        /* Last thing that main() should do */
        pthread_exit(NULL);

        puts("Completed processing.");
        double totalTime = 0.0;
        for (int z = 0; z < threadcount; z++) {
            pthread_arg ar = pthreadargs[z];

            printf("Thread %d took %g to process %d rows and %d columns.\n", z,
                    ar.execution_time, ar.endz - ar.start, ar.col);

            totalTime += ar.execution_time;
        }

        printf(
                "It took the total time of %g, to compute the dot product of the matrices.\n",
                totalTime);

        //free memory
        free(matrix.data);
        for (int k = 0; k < threadcount; k++) {
            free(pthreadargs[k].data);
            free(pthreadargs[k].result_set);
        }

    } while (filename[0] != 'Q' || filename[0] != 'q');
}

这是pthread调用的函数

void * compute_dot_product(void * inputArgs) {
    double startTime, endTime;
    pthread_arg * args = inputArgs;

    /*Compute the dimension of the result matrix*/

    int col, row, start, endz;
    col = args->col;
    start = args->start;
    endz = args->endz;
    row = endz - start;

    fprintf(stderr, "after %p\n", args->result_set);

    //create a pointer to the two array
    double **arr1 = args->data;
    double **arr2 = arr1;

    //begin the computation
    int x;
    startTime = seconds();

    //calculate the dot product the two matrices.
    for (x = 0; x < col; x++) {
        double colProduct = 0.0;
        for (int y = start; y < endz; y++) {
            colProduct += arr1[y][x] * arr2[y][x];
        }

        //The code breaks here.
        args->result_set[x] = colProduct;
   }
    endTime = seconds();

    double diff = endTime - startTime;
    args->execution_time = diff;
    return (void *) 4;
}

这是我的结构定义

typedef struct
{
    int NROWS; /*for m rows*/
    int NCOLS; /*for n columns*/
    double ** data;
} matrix_def;

typedef struct
{
    double execution_time;
    matrix_def matrix;

} compute_result;

typedef struct{
    int row;
    int col;
    int start;
    int endz;
    double execution_time;
    double **data;
    double *result_set;
} pthread_arg;

二维矩阵的内存分配。

/*dynamically allocate array based on the read size*/
    matrix.data =  (double **) malloc(sizeof(double *) * M);


    if(matrix.data != NULL){
        int x;
        for(x = 0; x < M; x++){
            matrix.data[x] = (double) malloc(sizeof(double) * N);
        }
    }else{
        fprintf(stderr, "Unable to allocate memory\n");
        exit(1);
    }

初始化矩阵函数

matrix_def initialize_matrix(char *argv)
{
    int ret_code;
    MM_typecode matcode;
    FILE *f;
    int M, N, nz;
    int i;
    matrix_def matrix;

    if((f = fopen(argv, "r")) == NULL)
    {
        fprintf(stderr, "Reading file: '%s' failed", argv);
        exit(1);
    }

    /*Read matrix banner*/
    if(mm_read_banner(f, &matcode) != 0)
    {
        printf("Could not process Matrix Market banner. \n");
        exit(1);
    }

    /*Check if the current matrix is supported.*/
    if(mm_is_complex(matcode) && mm_is_matrix(matcode) && mm_is_sparse(matcode))
    {
        printf("Sorry, this application does not support ");
        printf("Market Matrix type: [%s]\n", mm_typecode_to_str(matcode));
        exit(1);
    }


    /*find out size of the sparse matrix...*/
    if((ret_code = mm_read_mtx_crd_size(f, &M, &N, &nz)) != 0)
        exit(1);


    /*Assign m, n sizes.*/
    matrix.NROWS = M;
    matrix.NCOLS = N;

    /*dynamically allocate array based on the read size*/
    matrix.data =  (double **) malloc(sizeof(double *) * M);


    if(matrix.data != NULL){
        int x;
        for(x = 0; x < M; x++){
            matrix.data[x] = (double *) malloc(sizeof(double) * N);
        }
    }else{
        fprintf(stderr, "Unable to allocate memory\n");
        exit(1);
    }



    /*Iterate through the created memory location and fill it with zeros*/
    int a, b;
    for(a = 0; a < M; a++){
        for(b = 0; b < N; b++){
            matrix.data[a][b] = 0;
        }
    }

    /*Read the matrix*/
    for(i = 0; i < nz; i++)
    {
        int I = 0, J = 0;
        double val = 0;
        fscanf(f, "%d %d %lg\n", &I, &J, &val);


        //since the matrix market file starts off at
        //1,1 we have to subtract 1 from the index
        //to account for the array which starts off at
        // 0,0
        matrix.data[--I][--J] = val;
    }

    if(f != stdin)
        fclose(f);

    return matrix;
}

任何帮助将不胜感激,因为我对公式不是很确定。谢谢

此处定义的arg对象:

        pthread_arg arg = { matrix.NROWS, matrix.NCOLS, startRow, endRow,
                0.0, NULL, NULL };

线程仍在 运行 时超出范围。您需要以某种方式防止这种情况发生,例如通过在堆上分配它。

arg 在执行 pthread 之前超出范围。将您的呼叫更改为

 rc = pthread_create(&threads[i], NULL, compute_dot_product, (void *) &pthreadargs[i]);

您还需要 pthread_join 才能退出,以防线程未完成。

编辑

1) 将您的 pthread_exit 替换为

int rv;
for (i = 0; i < threadcount; ++i)
    pthread_join(thread[i], &rv);

您通常会在线程内调用 pthread_exit(如 compute_dot_product)作为异常退出。这可能是您的程序中断的原因。

2) 在您退出时,我不知道您是如何分配内存的,但这是您的代码可能被破坏的潜在区域。如果您将内存分配为

matrix.data = malloc(sizeof(double*) * matrix.NROWS);
matrix.data[0] = malloc(sizeof(double) * matrix.NROWS * matrix.NCOLS);
for (i = 1; i < matrix.NROWS; ++i)
    matrix.data[i] = matrix.data[i - 1] + matrix.NCOLS;

那么你应该免费为

free(matrix.data[0]);
free(matrix.data);

如果您已单独分配每一行,则在释放之前释放所有行 matrix.data。

3) 由于 matrix.data 已被释放,pthreadargs[k].data 不应被释放,因为它指向已被释放的相同内存区域。