简体   繁体   中英

Can i write array[x][x] to a pipe?

im trying to run this on Linux, this program supposed to pass arrays of numbers with pipes, to the children, and each children calculate the gcd of the pairs. But I get "Segmentation fault(core dumped)" ERROR. I've checked the child's process, and right after the read() i tried to print string just for check and it doesn't work. The weird thing that the read not returns -1, which means it worked. is it possible to write char **arr; into a pipe? or is it to big for a pipe and this is why it crashes. Thank you for any help.

BTW, the./v2_child1 is fine, the problem comes before the execvp()

#include <stdarg.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_LINE_LENGTH 100
#define FILE_NAME "numbers.txt"

char** readFromTextFile(char *fileName) {

    FILE *f = fopen(fileName, "r");
    if (f == NULL) {
        printf("Error while opening file!");
        return NULL;
    }
    char *line = (char*) malloc(MAX_LINE_LENGTH * sizeof(char));
    char **pairs = (char**) malloc(50 * sizeof(char*));
    int counter = 0;

    while (!feof(f)) {
        char *num1 = (char*) malloc(sizeof(char) * 2);
        char *num2 = (char*) malloc(sizeof(char) * 2);
        fgets(line, MAX_LINE_LENGTH, f);
        sscanf(line, "%s   %s", num1, num2);
        pairs[counter] = num1;
        pairs[counter + 1] = num2;
        counter += 2;
    }
    pairs[counter] = NULL;
    fclose(f);
    return pairs;
}

int numOfPairs(char **arr) {
    int count = 0;
    while (arr[count] != NULL) {
        count += 1;
    }
    if ((count % 2) != 0) {
        printf("odd amount off numbers");
        return -1;
    } else {
        return count / 2;
    }
}

int main(int argc, char *argv[]) {

    //read the pairs of numbers into array
    char **numbers = readFromTextFile(FILE_NAME);
    //returns the num of pairs to check
    int num_pairs = numOfPairs(numbers);
    //initialize the pipes
    int write_pipe[2], read_pipe[2];

    if (pipe(write_pipe) == -1 || pipe(read_pipe) == -1) {
        fprintf(stderr, "Pipe operation failed!");
        exit(0);
    }

    //child --> parent
    int PARENT_READ = read_pipe[0]; // IN
    int CHILD_WRITE = read_pipe[1]; // OUT

    //parent --> child
    int CHILD_READ = write_pipe[0];
    int PARENT_WRITE = write_pipe[1];

    pid_t status = fork(); // create child number 1

    if (status < 0) { // error ocurred
        fprintf(stderr, "Error with fork");
        exit(0);

    } else if (status > 0) { // parent go here 

        char **to_child1 = (char**) malloc(sizeof(char*) * (num_pairs / 2) * 2);
        for (int i = 0; i < num_pairs / 2; ++i) {
            to_child1[2 * i] = numbers[2 * i];
            to_child1[2 * i + 1] = numbers[2 * i + 1];
        }

        if (close(CHILD_READ) == -1)
            perror("problem while close CHILD_READ");
        if (write(PARENT_WRITE, to_child1, sizeof(char*) * (num_pairs / 2) * 2)
                == -1)
            perror("problem while write to PARENT_WRITE");

        if (close(PARENT_WRITE))
            perror("problem while close PARENT_WRITE");

        printf("wrote from parent to pipe\n\n");


    } else { // child process
        char **first_half = (char**) malloc(
                sizeof(char*) * (num_pairs / 2) * 2);
        printf("Hello form son 1\n");
        if (close(PARENT_WRITE) == -1)
            perror("Error while close");
        read(CHILD_READ, first_half, sizeof(char*) * (num_pairs / 2) * 2);

        printf("child got here"); // not printing this*

        if (close(PARENT_READ) == -1) //read is unused
            perror("Error while close");
        if (dup2(CHILD_WRITE, STDOUT_FILENO) == -1) { //redirecting Stdout to pipe.
            perror("dup2 error");
        }

        char *args[num_pairs / 2 + 1];
        args[0] = "./v2_child1";
        for (int i = 1; i < num_pairs / 2 + 1; ++i) {
            args[i] = first_half[i];
        }
        execvp(args[0], args);

    }
    wait(NULL);
    char **gcds = (char**) malloc(sizeof(char*) * (num_pairs / 2));
    close(CHILD_WRITE);
    read(PARENT_READ, gcds, sizeof(int));
    for (int i = 0; i < num_pairs / 2; ++i) {
        printf("The gcd of %d and %d is: %d - calculated from child 1\n",
                atoi(numbers[i * 2]), atoi(numbers[i * 2 + 1]), atoi(gcds[i]));
    }

    /// another child to be created
}

to_child1 is an array of pointers. Pointer values are only meaningful within the process that created them. Writing a pointer into the pipe does not copy the data that it points to. So when the child process reads the pointers, it doesn't have the strings they point to.

Since all the strings are just 1 character, there's no need to use an array of pointers, just make an array of char , and write that to the pipe.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM