Читать всю трубу - с - PullRequest
       77

Читать всю трубу - с

0 голосов
/ 24 апреля 2018

У меня есть некоторые трудности с этим кодом.Мне нужно получить всю информацию из трубы в конце.Но я получаю ошибку segfault.

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

int main(void){

    int tube[2];

    if(pipe(tube) == -1){
        perror("Erreur");
        exit(1);
    }

    dup2(tube[1],1);

    printf("Few lines \n");
    printf("of an undefined size. \n");

    while (!feof(tube[0])) {
        char temp = fgetc(tube[0]);
        printf("chaine : %c\n", temp);
    }

    return 0;
}

Если у вас есть представление о том, как я могу решить эту проблему, пожалуйста, объясните.

Ответы [ 3 ]

0 голосов
/ 24 апреля 2018

Функция pipe возвращает пару файловых дескрипторов int, а не FILE. Это означает, что вы можете использовать read, write или close на них, но ни fgetc, ни feof.

Кроме того, while(!feof(file)) (почти) всегда неверно , поскольку флаг установлен после неудачного чтения до конца файла.

И это еще не все. Вы получаете EOF только на конце чтения канала, когда все дескрипторы на конце записи закрыты. Поэтому вы должны закрыть или очистить stdout, чтобы убедиться, что все символы были записаны в канал, закройте дескриптор файла 1, если вы не закрыли стандартный вывод, и закройте tube[1], который по-прежнему является файловым дескриптором для конца записи труба.

Таким образом, вы можете заменить цикл while на:

close(tube[1]);
fclose(stdout);

while (1) {
    char temp;
    if (read(tube[0], &temp, 1) < 1) break;
    fprintf(stderr, "chaine : %c\n", temp);
}

Он исправляет SEGFAULT, вызванный использованием feof и fgetc для чего-то, что не является FILE, и обеспечивает правильное закрытие конца записи файла перед чтением его содержимого, чтобы получить хороший конец файла состояние.

0 голосов
/ 24 апреля 2018

Но я получаю ошибку segfault. ? это означает, что вы не правильно прочитали предупреждение компилятора. когда вы делаете feof(tube[0]), он говорит, что feof() ожидает FILE*, но вы предоставили тип int (tube[0] является inetger).

/ usr / include / stdio.h: 828: 12: примечание: ожидается "struct FILE *", но аргумент имеет тип "int"

Итак, первым делом всегда читайте предупреждения компилятора и код компиляции с -Wall флажками.

Этот fgetc(tube[0]); не является способом чтения данных из file descriptor, используйте системный вызов read() для чтения данных из файловых дескрипторов, а не fgetc(). fgetc() вы можете использовать, если открыли файл с fopen().

Также

dup2(tube[1],1); /* this is not expected one which you want*/

используйте вот так

dup2(1,tube[1]);/*stdout get duplicated with tube[1] i.e whatever you
                        write on stdout will be written into write end of pipe*/

Вот простой пример.

char temp[100];
        int ret = 0;
        ret = read(tube[0],temp,sizeof(temp));/*reading from pipe*/
        if(ret == -1)   {
                perror("read");
                return 0;
        }
        else {
                temp[ret] = '\0';/*read returns no of items read, so put null
                                        at last otherwise you may get some junk data  */
                printf("%s",temp);
        }

Прочитайте man 2 read & man 2 dup2, чтобы узнать, как работают эти системные вызовы ..

0 голосов
/ 24 апреля 2018

Вы используете функцию, которая возвращает один символ (fgetc), а затем обрабатывает это значение как указатель на строку в вашем вызове printf. Вы также сохраняете этот символ как адрес указателя на символ, а не как собственно символ, поэтому, когда printf начинает читать вашу строку, он читает нехватку памяти, которой он не владеет. fgetc возвращает сам символ, вам нужна переменная char, а не char *.

Попытка:

while (!feof(tube[0])) {
    char temp = fgetc(tube[0]);
    printf("chaine : %c\n", temp);
}
...