神秘的linux回溯和内存映射

时间:2017-12-10 17:35:51

标签: c linux memory-management linux-kernel free

在处理内存分配,valgrind和gdb时,我不得不写一个带有无效free的简单c程序:

#include <stdlib.h>
#include <stdio.h>

int main (void)
{
    int* arr = (void*) malloc(100 * sizeof(int));
    arr[50] = 10;
    free(arr + (20 * sizeof(int)));
    printf("arr[50] = %d\n", arr[50]);
    return 0;
}

根据需要产生错误:

*** Error in `./allocWithFunnyFree': free(): invalid pointer: ... ***
======= Backtrace: =========
...
======= Memory map: ========
...

然后我试图通过将sdtoutstderr重定向到/dev/null来摆脱输出,但注意到输出仍然会被打印,让我感到困惑。

我使用调试器在free()调用之前向程序停止了一条指令,查找/proc/PID/fd目录并再次尝试将所有列出的fd重定向到/dev/null但仍然相同结果..

我在网上搜索了答案并询问了我的一些同事,但是没有人可以向我解释这个输出是如何打印的,以及为什么它不能被重定向。

当然还有很多我不了解的关于操作系统/ linux的东西,但我希望你能帮助我理解这里发生了什么。
谢谢!

1 个答案:

答案 0 :(得分:4)

回溯(在glibc中)are printed to /dev/tty,它将是一个不同的文件描述符(它在程序中将是3)而不是1和2,而你的shell不知道它。

Glibc提供了一个环境变量LIBC_FATAL_STDERR_,您可以使用该变量将其重定向到其他位置。例如,您可以使用以下命令将回溯重定向到stderr:

$ export LIBC_FATAL_STDERR_=2
$ ./allocWithFunnyFre 2>free_backtrace

如果您在strace下运行程序,则可以更好地理解它(以及如何编写回溯)。