Using pipes and structures with dynamically allocated variables in C

I am writing a program that has to pass a matrix from the parent process to its child (which is why I am using an instruction fork()

). I just read this and this to solve the problem but I did not understand until now how to use instructions read()

and write()

to set up my channel. I know these instructions write a series of bytes, but I'm not sure if they are used with structs or dynamically allocated variables (like a matrix).

Here is the code I used for testing (note the comments I posted):

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>

// Structure definition (Matrix)
typedef struct {
    int **mat;
    int rows;
    int cols;
} Matrix;

int main() {
    // Create the pipe
    int file_desc[2];
    if (pipe(file_desc) != 0) exit(1);

    // Create two processes
    if (fork() == 0) {
        /** Instructions for the child process */
        // Read the matrix structure from the pipe
        Matrix *received = NULL;
        read(file_desc[0], received, sizeof *received);
        if (received != NULL) {
            // Print the received matrix
            int i, j;
            printf("The matrix I've just *received* from the parent is:\n");
            for (i = 0; i < received->cols; i++) {
                for (j = 0; j < received->rows; j++) printf("%d\t", received->mat[i][j]);
                printf("\n");
            }
        } else printf("received = NULL :'(\n");
    } else {
        /** Instructions for the parent process */
        /* Create a matrix dinamically.
         * In fact, in the real program I have a function to create a matrix given the
         * rows and columns, and fill it with random values, so it returns a Matrix *
         * (pointer to Matrix), but for testing purposes I've only written this
         * (also useful if I need an array of Matrix elements, for example)
         * */
        Matrix *myMatrix = calloc(1, sizeof *myMatrix);

        // Put the contents into the variable
        myMatrix->rows = 2;
        myMatrix->cols = 2;
        myMatrix->mat = calloc(myMatrix->rows, sizeof *(myMatrix->mat));
        int i, j;
        for (i = 0; i < myMatrix->cols; i++)
            (myMatrix->mat)[i] = calloc(myMatrix->cols, sizeof **(myMatrix->mat));

        // Fill the matrix with some values (testing)
        (myMatrix->mat)[0][0] = 4;
        (myMatrix->mat)[0][1] = 2;
        (myMatrix->mat)[1][0] = 1;
        (myMatrix->mat)[1][1] = 3;

        // Print the matrix
        printf("The matrix I've just filled in the parent is:\n");
        for (i = 0; i < myMatrix->cols; i++) {
            for (j = 0; j < myMatrix->rows; j++) printf("%d\t", myMatrix->mat[i][j]);
            printf("\n");
        }

        // Write the matrix structure to the pipe (here is where I have the problem!)
        write(file_desc[1], myMatrix, sizeof *myMatrix);

        // Wait for the child process to terminate
        wait(0);
        printf("The child process has just finished, the parent process continues.\n");
    }
    return 0;
}

      

Actually, I tried with a pointer to first int

and it worked. But when I run this program, I get this output:

The matrix I've just filled in the parent is:
4   2   
1   3   
received = NULL :'(
The child process has just finished, the parent process continues.

      

And I don't know why I'm getting NULL - I'm pretty sure I'm using the statement incorrectly write()

. Any help on this would be appreciated =)

EDIT: I think the matrix should be converted to text, for example, and then pass the string to the child, parse it, and convert back to the matrix structure. I don't know if this is the best approach. Is there any other approach besides this?

EDIT: I've tried the same code with a static variable (changing int **mat;

to int mat[2][2];

inside the structure declaration), but the user has to resize the matrix.

+3


source to share


1 answer


This is a serious problem:

Matrix *received = NULL;
read(file_desc[0], received, sizeof *received);

      



Received a null pointer. This one read

will try to write data to NULL, which is an invalid address. It would be much easier to write:

Matrix received;
read(file_desc[0], &received, sizeof received);

      

+1


source







All Articles