我在我的 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/