为什么 Valgrind 抱怨的是 printf 而不是我未初始化的计数器?

Why is Valgrind complaining about printf instead of my uninitialized counter?

我刚开始使用 Valgrind,我不确定收到的错误消息是否正确。例如,Valgrind 刚刚给了我一长串关于 printf() 基于未初始化内存进行跳转的警告。很明显,问题不在于 printf()。相反,我的程序正在提供 printf() 受污染的内存。

我成功制作了以下 MCVE:

#include <stdio.h>

int main(void)
{
    int d;
    d++;
    printf("%d\n", d);
    return 0;
}

很明显这里的问题出在d++。但是,Valgrind 仅在下一行中检测并警告我未初始化的内存使用情况,形式为 6 条消息

==12178== Conditional jump or move depends on uninitialised value(s)
==12178== at 0x4E7F79D: vfprintf (vfprintf.c:1636)
==12178== by 0x4E871F8: printf (printf.c:33)
==12178== by 0x1086D1: main (mcve.c:7)

我用

编译了这个

gcc mcve.c -g -O0

我 运行 Valgrind 与

valgrind --leak-check=yes ./a.out

然后我发现有--track-origins=yes。它试图提供帮助,但很容易因指针而丢失。例如,它不适用于下一个 MCVE:

#include <stdio.h>

int f2(int *p)
{
    (*p)++;
    return *p;
}

int f1(void)
{
    int d;
    return f2(&d);
}

int main(void)
{
    printf("%d\n", f1());
    return 0;
}

这里说错误在f1()的堆栈帧中。这有点帮助,但考虑到所涉及的性能损失,也许不值得。

如何才能充分利用 Valgrind?

Valgrind 中的一个深思熟虑的决定是它 抱怨 只是因为一些未初始化的内存被复制或类似。 只有当使用未初始化的内存改变了 您程序的行为。这种深思熟虑的选择避免了很多 false-positive 错误。

http://www.valgrind.org/docs/manual/mc-manual.html#mc-manual.uninitvals 获取更多信息。