【问题标题】:Do streams have to be closed when using popen使用 popen 时必须关闭流吗
【发布时间】:2010-11-29 14:35:49
【问题描述】:

正如标题所说,我不确定是否应该关闭使用 popen 打开的流。

我不确定的原因是因为每次我在使用 popen 打开的流上调用 pclose 时都会得到 -1 返回码。

如果我在此之后调用 perror,我会收到以下消息。

pclose:没有子进程

我在下面使用的代码基本上是运行命令并捕获其输出。我从最后一行得到错误(return pclose(fileListingStream);)

int executeCommand(char *command) {
    //The Stream to read that will contain the output of the command
    FILE *fileListingStream;
    char path[PATH_MAX];

    //Run the commmand in read mode
    fileListingStream = popen(command,"r");

    //Ensure that its not null before continuing
    if (fileListingStream == NULL)
        return EXIT_FAILURE;

    //Get the data from the stream and then print to the the console
    while (fgets(path, PATH_MAX, fileListingStream) != NULL)
        printf("%s", path);

    //Close the stream and return its return code
    return pclose(fileListingStream);
}

【问题讨论】:

  • 你的程序是否会忽略或处理SIGCHLD

标签: c popen


【解决方案1】:

是的,你应该这样做。有关pclose() 内部工作原理的说明,请参阅this answer。此外,您应该注意wait4() 中的错误可能是pclose() 中明显失败的原因。

更新0

如果FILE * 有效(在内部这由文件描述符不是-1 表示),pclose() fclose() 不会在出现错误时导致泄漏。值得注意的是,如果FILE * 无效,则无论如何也没有什么可清理的。正如我链接到的答案中所讨论的,pclose() 有额外的行为,即从 proc 文件链中删除FILE *,然后等待子进程终止。内部等待实际上是为pclose() 完成的倒数第二件事,此时一切都已清理完毕。等待之后,FILE 的内容立即被丢弃以表示其无效,无论waitpid() 中是否有任何错误都会发生这种情况。

鉴于您收到的错误ECHILD,我可以肯定地说,eglibc-2.11.1 下的pclose() 没有内存泄漏,并且至少在过去 1-4 年内可能存在任何 glibc 派生库。

如果您想完全确定,只需在valgrind 下运行您的程序,并触发ECHILD 错误。如果有任何泄露,Valgrind 会通知您。

【讨论】:

  • 如果 pclose 失败,我还需要担心内存泄漏吗? ,还有什么办法可以关闭文件。
【解决方案2】:

如果您的应用程序修改了SIGCHLD 的配置,它可能会干扰popen() 等待shell 退出的能力。

【讨论】:

    【解决方案3】:

    那个错误是ECHILD——意思是waitpid返回了一个错误,它不能得到子进程的返回状态。这可能是由进程创建的实际“命令”引起的。

    正如其他人提到的那样,您应该关闭,因为它会留下一个“悬空”文件描述符,并可能导致子进程无法及时清理。

    【讨论】:

      猜你喜欢
      • 2016-11-04
      • 2011-07-02
      • 1970-01-01
      • 2010-09-18
      • 2016-07-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-03
      相关资源
      最近更新 更多