Hi, I have to create a program that creates N child processes, and they muliply the matrix. I have some base codes but when I try to run them they give me segmentation error and I cant find the problem.

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#define BASEPID 9000
#define MAX_SIZE 1000

int matrix1[MAX_SIZE][MAX_SIZE], matrix2[MAX_SIZE][MAX_SIZE],
    result[MAX_SIZE][MAX_SIZE];

typedef struct {
  long priority;
  int index;
  int finished;
  int result[MAX_SIZE];
} matrix;

int main(int argc, char *argv[]) {
  int size = atoi(argv[1]), rows, cols, z, PID, proc, parent = 1,
      inbox, outbox, mailbox, status;
  matrix message;
  message.priority = 2;
  message.finished = 0;

  // Check matrix size
  if (size > MAX_SIZE) {
    printf("Matrix too large\n");
    exit(1);
  }

  // Generate matrices
  srand(time(NULL));
  for (rows = 0; rows < size; rows++) {
    for (cols = 0; cols < size; cols++) {
      matrix1[rows][cols] = rand();
      matrix2[rows][cols] = rand();
      result[rows][cols] = 0;
      sleep(0);
    }
  }

  // Initialize inbox
  inbox = msgget(BASEPID, 0600 | IPC_CREAT);
  if (inbox < 0) {
    printf("Could not initialize inbox");
    exit(1);
  }

  // Fire up processes
  long nprocs = sysconf(_SC_NPROCESSORS_ONLN) * 2;
  if (nprocs <= 0) {
    printf("No processors are available to this process.");
    exit(1);
  }
  int processes[nprocs], mailboxes[nprocs];
  for (proc = 0; proc < nprocs; proc++) {
    // Initialize inbox
    mailbox = msgget(BASEPID + 1 + proc, 0600 | IPC_CREAT);
    if (mailbox < 0) {
      printf("Could not initialize inbox");
      exit(1);
    }

    PID = fork();
    if (PID == 0) { // Child process
      parent = 0;
      outbox = inbox;
      inbox = mailbox;
      break;
    } else { // Parent process
      processes[proc] = PID;
      mailboxes[proc] = mailbox;
    }
  }

  // Do the matrix multiplication
  if (parent == 1) {
    // Populate queues
    for (rows = 0; rows < size; rows++) {
      message.index = rows;
      status = msgsnd(mailboxes[rows % nprocs], &message, sizeof(message) - sizeof(long), 0);
      //printf("Sent row %d to %d\n", rows, mailboxes[rows % nprocs]);
      if (status < 0) {
          perror("Could not populate queue");
          exit(1);
      }
    }

    //printf("Finished populating queues\n");

    // Empty mailbox
    for (rows = 0; rows < size; rows++) {
      status = msgrcv(inbox, &message, sizeof(message) - sizeof(long), 0, 0);
      for (cols = 0; cols < size; cols++) {
        result[message.index][cols] = message.result[cols];
      }
    }

    // Notify processes to end
    for (proc = 0; proc < nprocs; proc++) {
      message.finished = 1;
      //printf("Sending termination signal to %d\n", mailboxes[proc]);
      status = msgsnd(mailboxes[proc], &message, sizeof(message) - sizeof(long), 0);
      //printf("Successfully send termination signal to %d\n", mailboxes[proc]);
      if (status < 0) {
          perror("Could not send termination signal");
          exit(1);
      }
    }

    // Wait on children before exiting
    for (proc = 0; proc < nprocs; proc++) {
      waitpid(processes[proc]);
    }

    // Free inbox
    struct msqid_ds msqid_ds, *buf;
    buf = & msqid_ds;
    status = msgctl(inbox, IPC_RMID, buf);
    if (status < 0) {
        perror("Could not free inbox");
        exit(1);
    }

    printf("%*s%*d.0\t", 15, "fork", 15, size);
  } else {
    // Block on queue input, return resultant row
    while (1) {
      //printf("Listening on %d\n", inbox);
      fflush(stdout);
      status = msgrcv(inbox, &message, sizeof(message) - sizeof(long), 0, 0);
      if (status < 0) {
          perror("Could not receive message");
          exit(1);
      }
      if (message.finished == 1) {
        break;
      }

      memset(message.result, 0, size);
      //printf("Received message in inbox %d\n", inbox);

      for (cols = 0; cols < size; cols++) {
        for (z = 0; z < size; z++) {
          message.result[z] += matrix1[message.index][cols] * matrix2[cols][z];
        }
      }
      //printf("Sending calculated row to %d\n", outbox);
      status = msgsnd(outbox, &message, sizeof(message) - sizeof(long), 0);
      //printf("Sent calculated row\n");
      if (status < 0) {
          perror("Could not send response");
          exit(1);
      }
    }

    // Free inbox
    struct msqid_ds msqid_ds, *buf;
    buf = & msqid_ds;
    status = msgctl(inbox, IPC_RMID, buf);
    exit(0);
  }

  return 0;
}

What compiler are you using? Try commenting out large sections of the code so that you can narrow down the location of the error.

Or ... start bottom up ... and code in small steps ... making sure that it 'works' as expected, (gives exact desired output), at each step ... and that YOU UNDERSTAND EACH step!

There is no shortage of example code ... re. matrix multiplication ... on the web ... if you do a little search ... even here at Dani... lots!

Edited 2 Years Ago by David W: added comment

You may like to see a version that uses dynamic memory...

/*matrixStructMult2.c */

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

typedef int myType;

typedef struct twoDArray
{
    myType **data;
    int rows;
    int cols;
} Matrix ;


/*
   The 'struct' holds a 'pointer to a pointer to int' for the 2-D array ...  
   AND ALSO holds the number of rows and cols for the 2-D array.
*/
void createMatrix( Matrix*, int, int );
void showMatrix( const Matrix* );
void freeMatrix( Matrix* );



int main()
{
    int i, j, k;
    int r = 2, c = 3;
    int count = r*c*2;
    int sum = 0;
    Matrix M1, M2, M3;

    createMatrix( &M1, r, c );

    /* fill in some values ... */
    for( i = 0; i < M1.rows; ++i )
        for( j  =0; j < M1.cols; ++j )
            M1.data[ i ][ j ] = count--;

    createMatrix( &M2, c, r+2 );

    /* fill in some values ... */
    for( i = 0; i < M2.rows; ++ i )
        for( j = 0; j < M2.cols; ++j )
            M2.data[ i ][ j ] = count--;

    createMatrix( &M3, r, r+2 );


    /* product first two matrices ...*/

    for( i = 0; i < M1.rows; ++i )
        for( j = 0; j < M2.cols; ++j )
        {
            for( k = 0; k < M2.rows; ++k )
            {
                sum += M1.data[i][k]*M2.data[k][j];
            }
            M3.data[i][j] = sum;
            sum = 0;
        }


    puts( "\nMatrix1" );
    showMatrix( &M1 );

    puts( "\nx Matrix2" );
    showMatrix( &M2 );

    puts( "\n= Matrix3" );
    showMatrix( &M3 );

    puts( "\nfree3" );
    freeMatrix( &M3 );
    puts( "\nfree2" );
    freeMatrix( &M2 );
    puts( "\nfree1" );
    freeMatrix( &M1 );

    puts( "" );
    system( "pause" );
    return 0;
}


void createMatrix( Matrix* pM, int numrows, int numcols )
{
    int i, j;

    pM->data = malloc( sizeof(int*)*numrows );
    assert(pM->data);

    for( i = 0; i < numrows; ++i )
    {
        pM->data[ i ] = malloc( sizeof(int)*numcols );
        assert( pM->data[ i ] );
        for( j = 0; j < numcols; ++j )
            pM->data[i][j] = 0; /* initialize all to zero  */
    }
    pM->rows = numrows;
    pM->cols = numcols;
}

void showMatrix( const Matrix* pM )
{
    int i, j;
    for( i = 0; i < pM->rows; ++i )
    {
        for( j = 0; j < pM->cols; ++j )
            printf( "%4d ", pM->data[ i ][ j ] );
        puts( "" );
    }
}

void freeMatrix( Matrix* pM )
{
    int i;
    for( i = pM->rows-1; i >= 0 ; --i )
    {
        printf( "pM->data[%d] = %d . ", i, (int)pM->data[ i ] );
        free( pM->data[ i ] );
    }

    printf( "pM->data = %d . ", (int)pM->data );
    free( pM->data );
}

like to see an example that uses dynamic memory ...

Edited 2 Years Ago by David W: fixed comments

This article has been dead for over six months. Start a new discussion instead.