使用popen时必须关闭流

时间:2010-11-29 14:35:49

标签: c popen

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

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

如果我之后打电话给perror,我收到以下消息。

  

pclose:没有子进程

我在下面使用的代码基本上是运行一个命令并捕获它的输出。我从最后一行得到错误(返回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);
}

3 个答案:

答案 0 :(得分:5)

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

Update0

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

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

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

答案 1 :(得分:2)

如果您的应用程序修改了SIGCHLD的处置方式,则可能会影响popen()等待shell退出的能力。

答案 2 :(得分:0)

该错误是ECHILD - 意味着waitpid返回错误,无法获得子进程的返回状态。这可能是由于“命令”实际上是过程创建的原因所致。

正如其他人提到的那样你应该pclose,因为它留下了一个'悬空'文件描述符,并且可能导致子进程不能及时清理。