Могу ли я записать массив [x] [x] в трубу? - PullRequest
0 голосов
/ 24 апреля 2020

я пытаюсь запустить это на Linux, эта программа должна передавать массивы чисел с трубами дочерним элементам, и каждый дочерний элемент вычисляет gcd пар. Но я получаю "Ошибка сегментации (ядро сброшено)" ОШИБКА. Я проверил процесс ребенка, и сразу после read() я попытался напечатать строку только для проверки, и она не работает. Странная вещь, что read не возвращает -1, что означает, что он работал. Можно ли написать char **arr; в трубу? или это большой для трубы, и именно поэтому он падает. Спасибо за любую помощь.

Кстати, ./v2_child1 в порядке, проблема возникает до 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
}

1 Ответ

1 голос
/ 24 апреля 2020

to_child1 - это массив указателей. Значения указателя имеют смысл только в процессе, который их создал. Запись указателя в канал не копирует данные, на которые он указывает. Поэтому, когда дочерний процесс читает указатели, у него нет строк, на которые они указывают.

Поскольку все строки - всего 1 символ, нет необходимости использовать массив указателей, просто создайте массив char и запишите это в трубу.

...