c++ - 即使 stdout 和 stderr 被重定向,Unix 程序如何在屏幕上显示输出?

标签 c++ linux

我在我的 Ubuntu 机器上运行一个程序(实际上是 valgrind),并将 stdout 和 stderr 重定向到不同的文件。我惊讶地看到屏幕上出现一条短消息——这怎么可能?我怎么能自己在 C++ 程序中做到这一点?

编辑:这是我使用的命令和输出:

$ valgrind ./myprogram > val.out 2> val.err
*** stack smashing detected ***: ./myprogram terminated

EDIT2:多玩一点,结果是 myprogram 而不是 valgrind 导致了消息被打印,如下面的回答,看起来 gcc 堆栈粉碎检测代码正在打印到/dev/tty

最佳答案

它不是由 valgrind 编写的,而是由 glibc 编写的,并且您的 ./myprogram 正在使用 glibc:

#define _PATH_TTY   "/dev/tty"

/* Open a descriptor for /dev/tty unless the user explicitly
   requests errors on standard error.  */
const char *on_2 = __libc_secure_getenv ("LIBC_FATAL_STDERR_");
if (on_2 == NULL || *on_2 == '\0')
  fd = open_not_cancel_2 (_PATH_TTY, O_RDWR | O_NOCTTY | O_NDELAY);

if (fd == -1)
  fd = STDERR_FILENO;

...
written = WRITEV_FOR_FATAL (fd, iov, nlist, total);

以下是glibc的一些相关部分:

void
__attribute__ ((noreturn))
__stack_chk_fail (void)
{
  __fortify_fail ("stack smashing detected");
}

void
__attribute__ ((noreturn))
__fortify_fail (msg)
     const char *msg;
{
  /* The loop is added only to keep gcc happy.  */
  while (1)
    __libc_message (2, "*** %s ***: %s terminated\n",
            msg, __libc_argv[0] ?: "<unknown>");
}


/* Abort with an error message.  */
void
__libc_message (int do_abort, const char *fmt, ...)
{
  va_list ap;
  int fd = -1;

  va_start (ap, fmt);

#ifdef FATAL_PREPARE
  FATAL_PREPARE;
#endif

  /* Open a descriptor for /dev/tty unless the user explicitly
     requests errors on standard error.  */
  const char *on_2 = __libc_secure_getenv ("LIBC_FATAL_STDERR_");
  if (on_2 == NULL || *on_2 == '\0')
    fd = open_not_cancel_2 (_PATH_TTY, O_RDWR | O_NOCTTY | O_NDELAY);

  if (fd == -1)
    fd = STDERR_FILENO;

  ...
  written = WRITEV_FOR_FATAL (fd, iov, nlist, total);

关于c++ - 即使 stdout 和 stderr 被重定向,Unix 程序如何在屏幕上显示输出?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31301711/

相关文章:

python - 在 Linux 中工作时在 Python 中模拟 Ctrl-C 键盘中断

没有 fork 可以用 pipe 吗?

c++ - 模板类 C++ 友元函数

c++ - SFINAE练习时编译报错

c++ - 静态库的链接器错误

linux - 将 linux box 配置为具有静态 ip

c++ - 设计注意事项 - C++ 服务器开发

c++ - 使用模板选择正确的 vector

linux - 将文本中的所有单词替换为 Unix,但 Linux 和空格除外

c - 查找进程 linux(C 代码)的打开文件描述符?