Home > Back-end >  How do I fix this segmentation fault?
How do I fix this segmentation fault?

Time:11-21

I am trying to run a program I have written for multiplying to square NxN matrices. However, I am getting a segmentation fault error. I have working code for the program without threading. But I have been unsuccessful in adapting my code for multiple threads. I am attempting to run the code on a raspberry pi 4. The debugger states that the following line is where I receive the error signal SIGSEGV: args.A[i][j] = rand() % 100;

I have tried putting printf statements around the sections of code where I allocate memory, but they were never run, so I am assuming that seg faults happen before any of the code is actually ran. I did some research on the internet in regards to solving seg faults, and that is when I tried using the debugger, but I do not understand why it is having a problem with setting the matrix elements. Especially since my previous unthreaded program has the same line of code and runs without any errors. Feedback would be greatly appreciated. The following is my code:

/* Program must be passed exactly one integer that satisfies the following condition:
 * N % n = 0, where N is the square matrices' dimensions and n is the number of threads.
 */

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

#define N 2000

typedef struct __myarg_t
{
    FILE *Aptr, *Bptr, *Cptr;   // Files containing the matrices
    int **A, **B, **C, **T;     // Matrices A , B, resultant and transpose of B
    int rows;           // Number of rows each thread computes
    int cur;            // Current thread number
} myarg_t;

void *mythread(void *arg)
{
    myarg_t *m  = (myarg_t *) arg;
    int start = m->cur   * m->rows;
    int end = start   m->rows;

    // Matrix Multiplication for rows start:(end - 1)
    for (int i = start; i < end; i  )
    {
        for (int j = start; j < end; j  ) 
        {
            int num = 0;

            for (int k = 0; k < N; k  )
            {
                num  = m->A[i][k] * m->T[j][k];
            }

            m->C[i][j] = num;
        }
    }

    return NULL;
}

int main(int argc, char *argv[])
{
    if (argc != 2)
        {
        fprintf(stderr, "usage: main-first <#ofthreads>\n");
        exit(1);
    }

    pthread_t *thread;
    clock_t tic, toc;
    myarg_t args;
    int rc, n;

    args.cur = 0;
    args.rows = N/n;
    n = atoi(argv[1]);
    args.Aptr = fopen("A_multi.txt", "w");
    args.Bptr = fopen("B_multi.txt", "w");
    args.Cptr = fopen("C_multi.txt", "w");
    args.A = (int**)malloc(N * sizeof(int*));
    args.B = (int**)malloc(N * sizeof(int*));
    args.C = (int**)malloc(N * sizeof(int*));
    args.T = (int**)malloc(N * sizeof(int*));
    thread = (pthread_t *)malloc(n * sizeof(pthread_t));

    // Dynamically allocate memory for 2D Array
    for (int i = 0; i < N; i  )
        {
        args.A[i] = (int*)malloc(N * sizeof(int*));
        args.B[i] = (int*)malloc(N * sizeof(int*));
        args.C[i] = (int*)malloc(N * sizeof(int*));
        args.T[i] = (int*)malloc(N * sizeof(int*));
    }

    // Assign values to the elements of the Matrices
    for (int i = 0; i < N; i  )
    {
        for (int j = 0; j < N; i  )
        {
            args.A[i][j] = rand() % 100;
            args.B[i][j] = rand() % 100;
            args.T[j][i] = args.B[i][j];
        }
    }

    tic = clock();

    // Create threads
    for (int i = 0; i < n; i  ) 
    {
        rc = pthread_create(&thread[i], NULL, mythread, &args);
        
        if (rc != 0)
        {
            printf("pthread_create failed with thread %d.\n", i);
            exit(1);
        }
    }

    // Wait for threads to complete
    for (int i = 0; i < n; i  ) 
    {
        rc = pthread_join(thread[i], NULL);                                                                              
        if (rc != 0)
        {
            printf("ptphread_join failed with thread %d.\n", i);
            exit(1);
        }
    }

    toc = clock();
    
    printf("Elapsed: %f seconds\n", (double)(toc - tic) / CLOCKS_PER_SEC);

    // Write matrices to their output files
    for (int i = 0; i < N; i  )
    {
        for (int j = 0; j < N; j  )
        {
            fprintf(args.Aptr, "%d ", args.A[i][j]);
            fprintf(args.Bptr, "%d ", args.B[i][j]);
            fprintf(args.Cptr, "%d ", args.C[i][j]);
        }

        fprintf(args.Aptr, "\n");
        fprintf(args.Bptr, "\n");
        fprintf(args.Cptr, "\n");
    }

    // Deallocate memory
    for (int i = 0; i < N; i  )
    {
        free(args.A[i]);
        free(args.B[i]);
        free(args.C[i]);
        free(args.T[i]);
    }

    free(args.A);
    free(args.B);
    free(args.C);
    free(args.T);
    fclose(args.Aptr);
    fclose(args.Bptr);
    fclose(args.Cptr);

    return 0;

}




CodePudding user response:

  1. Change:
    int rc, n;
    ...
    args.rows = N/n;
    n = atoi(argv[1]);

to:

    int rc;
    ...
    int n = atoi(argv[1]);
    if(!n) {
      // atoi() will return for "0" or error
    }
    args.rows = N/n;
  1. The 2nd loop after the "Assign values" comment probably increments the wrong variable i but should be j. Otherwise i will be 2 * (N-1) which will overflow the arrays A, B and T which are of has N elements. This will cause your segfault.
  • Related