[英]Correct way of using fdopen
我的意思是将文件描述符与文件指针相关联并将其用于写入。 我把程序io.cc
下面:
int main() {
ssize_t nbytes;
const int fd = 3;
char c[100] = "Testing\n";
nbytes = write(fd, (void *) c, strlen(c)); // Line #1
FILE * fp = fdopen(fd, "a");
fprintf(fp, "Writing to file descriptor %d\n", fd);
cout << "Testing alternate writing to stdout and to another fd" << endl;
fprintf(fp, "Writing again to file descriptor %d\n", fd);
close(fd); // Line #2
return 0;
}
我可以交替注释第 1 行和/或第 2 行,编译/运行
./io 3> io_redirect.txt
并检查io_redirect.txt
的内容。 只要第 1 行没有被注释,它就会在io_redirect.txt
中产生预期的行Testing\n
。 如果第 2 行被注释,我会得到预期的行
Writing to file descriptor 3
Writing again to file descriptor 3
在io_redirect.txt
中。 但是如果没有注释,这些行就不会出现在io_redirect.txt
中。
fdopen
的正确方法是什么? 注意。 这似乎是从 C/C++ 智能写入任意文件描述符的(部分)答案的正确方法我说“部分”,因为我可以使用 C 风格的fprintf
。 我仍然想使用 C++ 风格的stream<<
。
编辑:我忘记了fclose(fp)
。 这“关闭”了问题的一部分。
这是为什么?
打开的 stream (“流”是打开的FILE*
)是块缓冲的,因此在刷新文件之前没有任何内容写入目标。 退出应用程序会关闭所有打开的流,从而刷新 stream 。
因为在刷新 stream 之前关闭了底层文件描述符,所以程序的行为是未定义的。 我真的建议您阅读posix 2.5.1 Interaction of File Descriptors and Standard I/O Streams (尽管它是用可怕的语言编写的),从中:
...如果使用了两个或多个手柄,并且其中任何一个是 stream,应用程序应确保它们的动作按如下所述进行协调。 如果不这样做,结果是未定义的。
...
对于第一个手柄,适用以下第一个适用条件。 ...
...
如果它是一个 stream,它对写入或附加打开(但也不是对读取打开),应用程序要么执行 fflush(),要么关闭 stream。
“句柄”是文件描述符或 stream。 “活动句柄”是您使用的最后一个句柄。
fp
stream 是打开以附加到文件描述符3
的活动句柄。 因为fp
是一个活动句柄并且没有刷新,并且您使用close(fd)
将活动句柄切换到fd
,所以您的程序的行为是未定义的。
我的猜测是什么,最有可能发生的是您的 C 标准库实现在main
返回后调用fflush(fp)
,因为fd
已关闭,某些内部write(3, ...)
调用返回错误并且没有任何内容写入 output .
使用 fdopen 的正确方法是什么?
您提出的用法是使用fdopen
的正确方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.