正如标题所说,我不确定是否应关闭使用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);
}
答案 0 :(得分:5)
是的,你应该。有关pclose()
内部工作原理的说明,请参阅this answer。此外,您应该注意wait4()
中的错误可能是pclose()
中明显失败的原因。
如果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,因为它留下了一个'悬空'文件描述符,并且可能导致子进程不能及时清理。