cin.tellg возвращает -1 при получении ввода из канала - PullRequest
0 голосов
/ 31 декабря 2018

У меня есть случай, когда мне нужно передать выходные данные дочернего процесса в ifstream.

Я пытаюсь как создать ifstream из файлового дескриптора, используя метод здесь: Каксоздать f ++ cstream из файлового дескриптора POSIX?

, и я также пытаюсь просто использовать канал из дочернего stderr в мой собственный stdin и использовать cin в качестве потока.

В обоих случаях я получаю -1, когда я вызываю tellg.

Вот мой код с каналом от дочернего stderr к родительскому stdin:

#include <iostream>

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

using namespace std;

int
main()
{
    int mypipe[2];

    pipe(mypipe);

    dup2(mypipe[0], STDIN_FILENO);
    dup2(mypipe[1], STDERR_FILENO);

    __pid_t pid = fork();

    if(pid == 0)
    {
        // this is a process that outputs stuff into std::err
        char* argv[] = {"copy-feats", nullptr};

        int ret = execvp(argv[0], argv);

        exit(ret);
    }

    int status;
    waitpid(pid, &status, WNOHANG);

    cin.clear(); // attempting to clear the error state. Not working.
    long size = cin.tellg();
    cout << size << endl;
}

, как я уже сказал, вывод Tellgэто -1.

думал, что если я попытаюсь использовать getline (cin, some_string), я действительно смогу увидеть выходные данные дочерней программы.

Я попытался создать поток изтруба, но она все равно дает мне -1. ​​

Вот код, который я использовал:

#include <iostream>
#include <fstream>
#include <ext/stdio_filebuf.h>

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

#define READ_FD  0
#define WRITE_FD 1

using namespace std;

using FilebufType = __gnu_cxx::stdio_filebuf<std::ifstream::char_type>;

int
main()
{
    int mypipe[2];

    pipe(mypipe);

    __pid_t pid = fork();

    if(pid == 0)
    {
        dup2(mypipe[WRITE_FD], STDERR_FILENO);
        char* argv[] = {"copy-feats", nullptr};

        int ret = execvp(argv[0], argv);

        exit(ret);
    }

    int status;
    waitpid(pid, &status, WNOHANG);

    FilebufType filebuf(mypipe[READ_FD], std::ios::in);
    istream is(&filebuf);

    is.clear();
    auto size = is.tellg();
    cout << size << endl;
}

Заранее спасибо.

1 Ответ

0 голосов
/ 31 декабря 2018

На практике tellg() возвращает фактическую позицию файла, только когда входной поток является реальным файлом.То есть, когда входным потоком является std::ifstream, и только тогда, когда нижележащий файл является простым файлом.

Трубы и другие непрозрачные файлы не имеют представления о позиции файла.

В Linux, который вы используете, tellg() обычно реализуется (косвенно, но здесь это не актуально) с использованием lseek(2), а в документации lseek(2) явно указываетсячто он возвращает ошибку ESPIPE, если дескриптор файла представляет собой канал.И ошибка возврата, в конце концов, переводится в tellg(), возвращая -1.

...