【问题标题】:How can I handle _popen() errors in C?如何处理 C 中的 _popen() 错误?
【发布时间】:2019-11-15 13:20:18
【问题描述】:

早上好; 现在,我正在编写一个程序,该程序对物理过程进行蒙特卡罗模拟,然后将生成的数据通过管道传输到 gnuplot 以绘制图形表示。模拟和绘图工作得很好;但我有兴趣打印一条错误消息,通知用户未安装 gnuplot。为了解决这个问题,我尝试了以下代码:

#include <stdio.h>
#include <stdlib.h>
FILE *pipe_gnuplot;
int main() 
{
    pipe_gnuplot = _popen("gnuplot -persist", "w");
    if (pipe_gnuplot==NULL)
    {
        printf("ERROR. INSTALL gnuplot FIRST!\n");
        exit (1);
    }
    return 0;
}

但是,不是打印我的错误消息,而是出现“gnuplot 不被识别为内部或外部命令、可运行程序或批处理文件”(该程序在 Windows 上运行)。我不明白我做错了什么。根据 _popen 文档,如果管道打开失败,则应返回 NULL。你能帮我解决这个问题吗?提前致谢,如果问题非常基本,我们深表歉意。

【问题讨论】:

    标签: c windows pipe popen


    【解决方案1】:

    popen(或_popen)的错误处理很困难。

    popen 创建一个管道和一个进程。如果失败,您将得到NULL 结果,但这仅在极少数情况下发生。 (没有更多的系统资源来创建管道或进程或错误的第二个参数)

    popen 将命令行传递给 shell (UNIX) 或命令处理器 (Windows)。如果系统无法分别执行 shell 或命令处理器,我不确定您是否会得到 NULL 结果。

    命令行将由 shell 或命令处理器解析,错误会像手动输入命令一样被处理,例如导致错误消息和/或非零退出代码。

    成功的popen 仅意味着系统可以成功启动shell 或命令处理器。没有直接的方法来检查执行命令的错误或获取命令的退出代码。

    如果可能,我通常会避免使用popen

    如果您想专门针对 Windows 进行编程,请检查是否可以从 Windows API 函数(如 CreateProcess)获得更好的错误处理。

    否则,您可以将命令包装在一个脚本中,该脚本检查结果并打印您可以阅读和解析的特定消息,以区分成功和错误。 (我不推荐这种方法。)

    【讨论】:

    • 非常感谢您的回答!我将尝试使用CreateProcess()
    【解决方案2】:

    只是为了搭载@Bodo 的回答,在与 POSIX 兼容的系统上,您可以使用 wait() 等待单个子进程返回,并获取其退出状态(如果命令是,则通常为 127未找到)。

    由于您在 Windows 上,因此您拥有 _cwait(),但这似乎与 _popen 的实现方式不兼容,因为它需要子进程的句柄,而 _popen 不会返回或提供任何明显的访问权限。

    因此,似乎最好的办法是通过手动创建管道并使用spawn[lv][p][e] 函数之一生成进程来手动重新实现popen()。实际上,_pipe() 的文档提供了一个示例,说明了如何执行此操作(尽管在您的情况下,您希望将子进程的 stdin 重定向到管道的写入端)。

    我还没有尝试写一个例子。

    【讨论】:

    • 感谢您的回答!最后,我使用了CreateProcess() 并将我的程序与 gnuplot 的副本一起分发到同一文件夹中。我知道这不是理想的方法,但它是一种确保我的程序可以启动 gnuplot 的简单方法。
    猜你喜欢
    • 1970-01-01
    • 2010-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多