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

Cha*_*had 20 c++ linux

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

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

$ valgrind ./myprogram > val.out 2> val.err
*** stack smashing detected ***: ./myprogram terminated
Run Code Online (Sandbox Code Playgroud)

EDIT2:玩了一下,事实证明myprogram,而不是valgrind,正在打印消息,并且如下面的回答,它看起来像gcc堆栈粉碎检测代码正在打印到/ dev/tty

Ser*_*kov 16

它不是由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);
Run Code Online (Sandbox Code Playgroud)

以下是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);
Run Code Online (Sandbox Code Playgroud)

  • 您可能想要添加,通过在大多数系统上打开`_PATH_TTY`("/ dev/tty"`)来写入控制台的目录,因为这是实际的问题. (3认同)
  • @Yakk:是的,`myprogram`使用glibc,因此在`./ myprogram`进程的上下文中调用例程.是的,它确实继承了`valgrind`的stdout和stderr - 但它不会写入stdout或stderr.它似乎明确地打开了`_PATH_TTY`,这可能类似于`/ dev/tty`.通常,程序可以显式写入`/ dev/tty`,绕过`stdout`和`stderr`. (2认同)