无法使用重定向标准输出调用 g++

Can't invoke g++ with redirected stdout

本文关键字:标准输出 调用 g++ 重定向      更新时间:2023-10-16

我希望调用 g++ 并获取输出。这是我的代码:

#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <iostream>
#include <boost/optional.hpp>
#include <vector>
#include <string>
namespace Util
{
    template<typename T>
    using optional = boost::optional<T>;
}
namespace Wide
{
    namespace Driver
    {
        struct ProcessResult
        {
            std::string std_out;
            int exitcode;
        };
        ProcessResult StartAndWaitForProcess(std::string name, std::vector<std::string> args, Util::optional<unsigned> timeout);
    }
}
#include <unistd.h>    
#include <sys/types.h>    
#include <sys/wait.h> 
#include <iostream>
#include <fcntl.h>
Wide::Driver::ProcessResult Wide::Driver::StartAndWaitForProcess(std::string name, std::vector<std::string> args, Util::optional<unsigned> timeout) {
    int filedes[2];
    pipe(filedes);
    pid_t pid = fork();
    if (pid == 0) {
        while ((dup2(filedes[1], STDOUT_FILENO) == -1) && (errno == EINTR)) {}
        auto fd = open("/dev/null", O_RDWR);
        while ((dup2(fd, STDIN_FILENO) == -1) && (errno == EINTR)) {}
        //freopen("/dev/null", "rw", stdin);
        //freopen("/dev/null", "rw", stderr);
        //close(filedes[1]);
        close(filedes[0]);
        std::vector<const char*> cargs;
        cargs.push_back(name.c_str());
        for (auto&& arg : args)
            cargs.push_back(arg.c_str());
        cargs.push_back(nullptr);
        execv(name.c_str(), const_cast<char* const*>(&cargs[0]));
    }
    std::string std_out;
    close(filedes[1]);
    char buffer[4096];
    while (1) {
        ssize_t count = read(filedes[0], buffer, sizeof(buffer));
        if (count == -1) {
            if (errno == EINTR) {
                continue;
            } else {
                perror("read");
                exit(1);
            }
        } else if (count == 0) {
            break;
        } else {
            std_out += std::string(buffer, buffer + count);
        }
    }
    close(filedes[0]);
    int status;
    ProcessResult result;
    result.std_out = std_out;
    waitpid(pid, &status, 0);
    if (!WIFEXITED(status))
        result.exitcode = 1;
    else {
        result.exitcode = WEXITSTATUS(status);
        if (result.exitcode != 0) {
            std::cout << name << " failed with code " << result.exitcode << "n";
        }
    }
    return result;
}
int main()
{
    auto r = Wide::Driver::StartAndWaitForProcess("g++", { "-std=c++14", "main.cpp" }, 150);
    std::cout << r.std_out << "!!!!n!!!!n" << r.exitcode << "n";
}

输出:

read: Bad file descriptor
g++ failed with code 1
!!!!
!!!!
1

只需调用g++ main.cpp -std=c++14 && ./a.out.

我使用了 strace,但它并没有真正提供任何更有趣的细节 - 进程运行,然后是 fork/exec,然后是上述错误。我可以使用上面的代码调用其他进程,所以我不知道g++有什么不同。我可以毫无问题地用popen调用 GCC,所以我不知道这里有什么不同。

这里的错误真的不是很有帮助。如何调用g++并获取输出?

这里的问题是你调用execv它需要一个可执行文件的完整路径作为其第一个参数。

您需要的是使用 PATH 环境变量的内容来查找可执行文件的execvp,因此只需要像 g++ 这样的名称。