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.
source to share
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);
source to share