【问题标题】:How to associate stderr with output stream如何将 stderr 与输出流相关联
【发布时间】:2019-04-16 05:52:13
【问题描述】:

当我尝试使用 fileno(stderr) 获取 stderr 的文件描述符时,结果是 -2 而不是 2。fileno 的文档说这可能是因为在没有控制台窗口 @987654325 的 Windows 应用程序中@ 与输出流无关。

我需要stderr 文件描述符,因为我想使用_dup2()stderr 重定向到管道,因此使用fprintf(stderr, "...")std::cerr << "..." 编写的所有内容都将重定向到管道。

我的问题是是否可以在没有控制台窗口的 gui 应用程序中获取 stderr 的文件描述符?我可以在调用fileno(stderr) 之前以某种方式打开默认的stderr 文件描述符吗?

编辑:
根据@darune 提出的想法,我设法通过首先调用freopen("temp.txt", "w",stderr) 然后调用fileno(stderr) 来获取文件描述符来将fprintf(stderr, "...") 重定向到管道。

我希望这样做,因为我想从不受我控制的外部库重定向数据。

【问题讨论】:

  • 简单的dup2(pipeFD, STDERR_FILENO);怎么样?尚未测试,但应该可以解决问题。
  • 我尝试使用 dup2(pipeFD, 2),因为 Windows 中没有定义 STDERR_FILENO。它编译并运行,但我无法从管道中读取我写给它的东西。无论如何,如果我有控制台应用程序,它可以正常工作。我假设 stderr 的某些内容未正确初始化?
  • 你能写到管道吗?还是您尝试重定向不受您控制的数据?
  • 我以为我有一个解决方案,但它涉及fork(MS的Windows无法做到这一点)。
  • @ctrl-alt-delor,是的,我想从不受我控制的外部库中重定向数据。

标签: c++ windows stderr


【解决方案1】:

std::cerr 可以在您的程序中重定向,但 stderr 不能(至少不是以我所知道的任何可移植或标准方式)。

您可以先使用std::freopen,然后可以使用std::_fileno() 获取有效的文件描述符。这可能不够,也可能不够,所以如果在那之后您需要发生任何其他事情,您将不得不从自己的程序内部监视文件(例如,ala.tailing 文件)并进行自定义处理。

【讨论】:

  • 嗨。如果可能的话,我想用管道制作它。如果我有控制台应用程序,Sir Digby Chicken Caesar 用pipes 提出的解决方案可以工作。我可以将 std::cerr 和 stderr 都重定向到我的自定义日志,但如果应用程序没有控制台窗口,则不能。
  • @ŽigaGolob 恐怕你不走运 - 就像我说的那样,你被 freopen 电话卡住了。但是为什么要使用 stderr 开头呢?我认为现在没有人真正将 stderr 用于任何事情。除非你别无选择(为什么?)。
  • 正如您所说,我别无选择,因为外部库使用fprintf(stderr, "...") 写入错误。无论如何,如果这是不可能的,我会感到惊讶/无法理解。如果我有控制台应用程序,为什么我可以这样做。有什么区别?
  • @ŽigaGolob 然后你坚持使用freopen 公开电话 - 也许如果你先使用它,你可以应用你链接的其他“黑客/解决方案”。
  • 我不确定我是否了解您在我的情况下如何使用freopen。实际上我已经尝试将stderr 重定向到两个临时文件并交替读取并且它正在工作。如果可能的话,现在我想用管道做到这一点。是不是建议我先用freopen重定向到物理文件再重定向到管道?
【解决方案2】:

它在 Unix 中的工作方式是 2 指的是内核中的表中的第 2 行。表中的这个条目可以指向文件或文件之类的东西(套接字、管道、文件、设备、什么都没有……)。因此,如果那里什么都没有,表槽仍将保留,并且可以用新值填充(使用dup?)。

然而这是 Unix,而微软的 Windows 不是 Unix。

【讨论】:

  • 因为这是对文件描述符如何工作的解释。并注意 MS 没有文件描述符(它只是伪造它)。
猜你喜欢
  • 2012-06-25
  • 1970-01-01
  • 1970-01-01
  • 2020-09-04
  • 1970-01-01
  • 2018-06-17
  • 2011-06-09
  • 1970-01-01
  • 2012-09-27
相关资源
最近更新 更多