从链接库中抑制输出到cout

时间:2010-08-26 14:19:30

标签: c++ linux linker

我需要将我的C ++程序与几个共享库链接起来,这些共享库会产生过多的输出到std::coutstd::cerr,使它们对我的用途都无用。我可以访问这些库的C ++源代码,但不能修改它们。

有没有办法将输出重定向到不同的流,或者在链接到我的代码时禁止输出?我更喜欢C ++中的一种干净的方式,但是担心那是不可能的,我也会对脏的链接器黑客感到高兴。此外,“代理libstdc++”也可以作为最后的手段。

我在Linux下使用GNU工具链(g++libtoolld)。

6 个答案:

答案 0 :(得分:4)

显然,freopen可以做到这一点。

答案 1 :(得分:2)

如果您不需要自己使用,最简单的方法是在启动程序时从命令行重定向标准输出和标准错误。

$ myprog >/dev/null 2>&1

如果你想自己使用它们,那就是改变他们使用的streambuf。有关how to do that here的一些代码和讨论。在这里发帖真的太长了。

答案 2 :(得分:2)

由于stdout(文件描述符1)和stderr(文件描述符2)对整个过程有效,并且您无法使程序的一部分指向不同的文件,因此只有一种方法可以执行此操作:使用dup(2)复制它们并在您自己的代码中使用这些文件描述符。关闭fd的1和2,open / dev / null进行写入,并使用dup2尝试将它们分别设置为1或2(如果尚未设置)。非常难看,但那确实有效。

答案 3 :(得分:1)

三个想法(我都不喜欢......):

  • 您可以使用cout更改正在写入的缓冲区cerr / rdbuf()。您可以在调用库中的函数之前每次执行此操作并在之后重置它(可能使用包装函数)。

  • 您可以永久更改缓冲区,并为您自己的应用程序使用不同的cout / cerr对象。

  • 您可以使用修改后的标准头文件来编译库。他们可以定义新的全局流对象cout_new并使用宏将cout重新定义为cout_new。您可以告诉编译器使用新版本的头文件来编译库(因此您不必修改它们的源代码)。

正如我所说,这些解决方案都没有“干净”,但你要求它...... :)

答案 4 :(得分:1)

好像没人看到它,这是我的链接器建议:

  1. 设置libc,提供您自己的write(),并将输出过滤到文件描述符12
  2. 将您自己的代码与libc静态链接,然后将共享版本设置为如上所述压制write()
  3. 设置libc,提供使用my_write()绕过write()的{​​{1}}功能。
  4. 通过传递dlsym()链接共享库时换行write。然后在名为-Wl,--wrap=write的函数中将任何输出压缩到文件描述符12。其他文件描述符应调用__wrap_write
  5. 请注意,对于那些不知道的人,文件描述符__real_write1对应2stdout,最终写入{{1} } / stderr机器。这通常会实现cout调用cerr,调用cout,在不同级别上具有不同级别的缓冲和恶作剧。

    您最好的选择是选项4,缺点是您必须调整共享库的最终链接。

    接下来最好是上面的选项2,缺点是你的最终可执行文件要大得多,但不必在你自己的代码中使用愚蠢的函数。

    链接

    插入

    包装

答案 5 :(得分:0)

如果它们确实通过std::coutstd::cerr输出,那么您可以替换这些对象的流缓冲区,但是您必须通过其他流重定向您自己的程序的输出。有关如何执行此操作,请参阅this question

但是,如果他们使用std::printf()等,那么这将无效。