【问题标题】:Streams printing and redirection流打印和重定向
【发布时间】:2011-08-19 18:08:12
【问题描述】:

我有一个程序打印(通过 printf)到 stdout 一些数据,还调用函数 *foo* 它还打印到stdout 一些数据[如何从 foo 完成打印的方式(实现)是未知的,我看不到 foo 的代码]。

我必须将所有内容从 stdout 重定向到 buffer 或文件。我尝试了几种方法

  1. freopen(file.txt, stdout) - 只有我的代码打印被写入 file.txt。从 foo 打印的内容丢失了。
  2. setbuf(buffer, stdout) - 只有我的代码打印被写入缓冲区。从 foo 打印的内容出现在标准输出中。(它出现在屏幕上)

什么可以解释这种行为?问题如何解决?

注意:此代码必须在跨操作系统(lunux/wind && mac OS)中工作。我使用 gcc 来编译代码,我有 cygwin

【问题讨论】:

  • 您必须在 C 中执行此操作吗?一个简单的 bash 脚本可以只获取标准输出并将其写入文件。
  • 对...你能看到 foo 的打印输出吗?通过什么机制?
  • @brc - 是的。当我不使用“重定向”时,我知道从 foo 打印的内容

标签: c redirect printf stdout


【解决方案1】:

foo 可能没有使用stdio 进行打印并为此直接调用操作系统。

我不知道 win32,但在 POSIX 上你可以使用dup2 来处理它。

/* Before the function foo is called, make `STDOUT_FILENO` refer to `fd` */
int fd;
fd = open(...);
dup2(fd, STDOUT_FILENO);

编辑

令我惊讶的是,win32 has _dup2 但它还有其他作用。

【讨论】:

  • 我想过这个解决方案。但是这段代码必须在跨操作系统(lunux/wind && mac OS)中工作。我使用 gcc 来编译代码,我有 cygwin。
  • 是的,但就像我说的它应该是跨平台的,所以它也应该在其他操作系统上工作
  • @Yakov 其他系统(你提到的那些)有dup2 :-)
  • _dup2 不会像您认为的那样做。在 Unix 系统上,系统调用最终会修改进程的文件描述符表,因此写入文件的任何内容都会受到影响。在 Windows 上,CRT 会产生类似 POSIX 的文件描述符的错觉,实际上是 HANDLE 的包装器,因此它有自己的 int-to-HANDLE 映射,而 _dup2 会影响什么;不是HANDLE 本身。据我所知,没有真正的 Windows 等效于 dup2,它将支持 HANDLE 的对象替换为另一个 HANDLE。 (如果有我会很感兴趣的。)
  • @asveikau 很高兴知道。我觉得这有点可疑(我的意思是 CreateFile 制作了一个 HANDLE 并且突然 dup2 需要一个 int ?)。
【解决方案2】:

你怎么知道foo() 正在打印到stdout?您是否尝试过将标准输出重定向到 shell 中的文件并查看来自foo() 的输出是否仍然出现在屏幕上?

如果文件重定向将foo() 的输出发送到文件,那么您可能需要重新调整文件描述符级别,如cnicutar 的回答。

如果文件重定向没有将foo() 的输出发送到文件,那么它可能正在写入stderr,或者它可能正在打开并使用/dev/tty 或类似的东西。您可以通过将stdoutstdout 分开重定向来测试stderr

your_program >/tmp/stdout.me 2>/tmp/stderr.me

如果它正在打开/dev/tty,输出仍然会出现在您的屏幕上。

您在哪个平台上?如果您可以跟踪系统调用(Linux 上的strace,Solaris 上的truss,...),那么您可能能够看到foo() 函数在做什么。您可以通过在调用函数之前和之后编写消息来帮助解决问题,并确保刷新输出:

printf("About to call foo()\n");
fflush(0);
foo();
printf("Returned from foo()\n");
fflush(0);

printf/fflush 调用将在跟踪输出中可见,因此出现在其间的内容由 foo() 完成。

【讨论】:

  • +1 事实上,我开始怀疑图书馆实际上是在写信给stderr
  • 在一些关于 foo 的手册中写到它写入标准输出
  • @Yakov:有时,手册是错误的。有时,手册是正确的,但软件并没有实现手册所说的软件实现的内容。手册是一个指标;但代码的实际行为表明手册和软件并不都正确。
  • @Yakov:如果您打算跨平台工作,您如何为不同的机器获取foo() 的不同副本?您是否从同一供应商处为每个平台购买库?你和卖家谈过吗?是否有可以替代foo() 的 API,它的工作大致相同,但报告结果的方式不同(例如,允许您指定应写入结果的文件流)?
  • @Jonathan Leffler:是的,我确实在屏幕上看到了
【解决方案3】:
什么可以解释这种行为?

当您调用的代码使用与您不同的 C 库时,我已经看到了这种行为。在 Windows 上,当一个 DLL 用 GCC 编译而另一个 DLL 用 Visual C++ 编译时,我曾经看到过这种事情。 stdio 的实现对于这些显然是不同的,以至于这可能是有问题的。

另一个是你调用的代码没有使用stdio。如果你在 Unix 上,你可以使用 dup2 来解决这个问题,例如。 dup2(my_file_descriptor, 1)。在许多实现中,如果您有FILE*,您可以说dup2(fileno(f), 1)。这可能不是便携式的。

【讨论】:

  • 此代码必须在跨操作系统(lunux/wind && mac OS)中工作。我使用 gcc 来编译代码,我有 cygwin
猜你喜欢
  • 2013-12-15
  • 1970-01-01
  • 1970-01-01
  • 2015-06-06
  • 1970-01-01
  • 2022-10-20
  • 1970-01-01
  • 1970-01-01
  • 2012-09-01
相关资源
最近更新 更多