复制未初始化数据时,为什么没有valgrind抱怨?

时间:2016-02-26 11:06:28

标签: c valgrind

根据手册,它没有:

  

重要的是要了解您的程序可以根据需要复制垃圾(未初始化)数据。 Memcheck观察到这一点并跟踪数据,但不抱怨。只有当您的程序试图以可能影响您的程序外部可见行为的方式使用未初始化的数据时,才会发出投诉。

问题是,是否有一些重要的理由以这种方式行事?是否有(通常)使用的构造复制未初始化的数据会触发误报?或者有没有办法让valgrind抱怨这个?

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

int fubar(void) {
     int a;

     return a;
}

现在我错误地回想起来,只是在某些情况下它是未定义的,例如,如果您正在使用未初始化的变量进行算术运算:

int fubar(void) {
    int a;

    a -= a;
    return a;
}

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

1 个答案:

答案 0 :(得分:2)

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

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

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

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

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

我认为,valgrind在这里抱怨并不好。

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

当未初始化的数据可能导致程序的非确定性行为时,Valgrind会尝试抱怨。或者反过来说:如果它可以排除这种情况,它会抱怨。因此,例如,当分支或系统调用参数依赖于未初始化的数据时,valgrind会抱怨。你可以在exit(a)之后加a -= a;来试试,结果是

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

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