如何判断一个流是否在调用fclose之前在C中关闭()
问题描述:
我有一个失败的C程序,并且我已经缩小到一个fork()
ed孩子试图关闭stdout和stderr,这些孩子被父母关闭在调用fork()
之前的过程 - 我假设这些流被传递给子进程。如何判断一个流是否在调用fclose之前在C中关闭()
我怎么能告诉我们,如果一个流之前尝试用C关闭后关闭它使用类似fclose(stdout)
答
UNIX上的C程序希望文件描述符0,1和2在启动时打开。如果你不想让他们去任何地方,打开/dev/null
和dup
它到那些文件描述符。
答
如果你在该级别的工作,你可能不应该使用C标准库的缓冲FILE
指针(stdin
& co),而是与其基本的file descriptor整数本身。
你应该能够做一些无害的操作,例如文件上的lseek(fd, 0, SEEK_SET)
来检测底层描述符是否有效。
答
您可以使用ftell()来检查。 如果它返回-1,那么你的流大多是关闭的。
答
在调用fclose()之后,任何使用 的流都会导致未定义的行为。
因此,如果是FILE *标准输出,则根本不能再使用stdout
,甚至不能检查其是否有效/开放。
您可以直接使用stdout的文件描述符,它是fd 1。
struct stat stbuf;
if(fstat(1,&stbuf) == -1) {
if(errno == EBADF) {
stdout isn't open/valid
}
}
要么缺少的东西或这不工作? 我试着在另一个else {}子句中调用fclose()(意思是fstat的结果不是-1),并且注意到它从未关闭流 - 即使当我确定它是有效的并且打开时 – radai 2010-03-03 10:33:21
看起来确实不可靠,是的。在我的系统上,发生的是fclose(stdout);确实关闭了fd。然而,无论出于什么原因,fclose都会触发加载“/usr/share/nls/nls.alias”,现在它会自由获取fd 1 - 以及以下fstat成功 - 但现在指的是/ usr/share/nls/nls.alias“,如果事情按不同的顺序调用,情况可能会有所不同,在'strace'下运行你的程序来看看会发生什么,你最好接受cafs的建议,并且不要关闭stdin/out/err ,而是将它们重定向到/ dev/null – nos 2010-03-03 17:20:31