为什么 valgrind 在复制未初始化的数据时不报错?

Why doesn't valgrind complain when copying uninitialized data?

根据手册,它没有:

It is important to understand that your program can copy around junk (uninitialised) data as much as it likes. Memcheck observes this and keeps track of the data, but does not complain. A complaint is issued only when your program attempts to make use of uninitialised data in a way that might affect your program's externally-visible behaviour.

问题是这样做是否有重要原因?是否有(常用)构造复制未初始化的数据会触发误报?或者有没有办法让 valgrind 抱怨这个?

我担心的是,在 C 中使用未初始化的变量具有未定义的行为 (IIRC),因此例如以下函数可能会发出鼻腔守护进程:

int fubar(void) {
     int a;

     return a;
}

现在我记错了,它只是在某些情况下是未定义的,例如,如果你正在用未初始化的变量进行算术运算:

int fubar(void) {
    int a;

    a -= a;
    return a;
}

所以这里出现了同样的问题。 valgrind 是否有一些重要原因允许使用未初始化数据进行算术运算?等。请注意,特别是如果它是浮点数据,它实际上可能会改变外部可观察到的行为,因为可能会启用 FP 错误捕获。

是的,这种情况经常发生。例如:

struct {
    char a;
    int b;
} s1, s2;

s1.a = '.';
s1.b = 31337;

memcpy (&s2, &s1, sizeof(s1));

在这里,您正在复制未初始化的字节(ab 之间的填充字节)。

我想,valgrind 没有在这里抱怨是件好事。

一般来说(回应你的算术例子):

Valgrind 尝试仅在未初始化的数据可能是您程序的不确定行为的原因时才发出警告。或者反过来:如果可以排除这种情况,它 不会 抱怨。因此,例如,当分支或系统调用参数依赖于未初始化的数据时,valgrind 会抱怨。您可以通过在 a -= a; 之后放置 exit(a) 来尝试,结果是

Syscall param exit_group(status) contains uninitialised byte(s)

即使通常结果在任何情况下都是 0。 (您可能必须声明 a volatile 以防止将其从代码中删除)