valgrind 给出了错误的未初始化大小
valgrind gives a wrong size of uninitialised
我从博客中看到的 sample2.c 代码使用 valgrind 说明未初始化的值。这是代码:
sample2.c:
1 #include <stdio.h>
2
3 int main()
4 {
5 int a[5];
6 int i,s;
7 a[0]=a[1]=a[3]=a[4]=0;
8
9 printf("%d\n",a[2]);
10 for(i=0;i<5;i++)
11 s += a[i];
12
13 if(s == 377)
14 printf("sum is %d\n",s);
15 return 0;
16 }
使用 gcc -g -o sample2 sample2.c
valgrind --leak-check=full --track-origins=yes ./sample2
我得到了下面的 valgrind 检查信息。
我不明白为什么在我的机器中由于 sizeof(int) == 4 而使用大小为 8 的未初始化值?我运行x64机器上的程序,所以这会是指针吗?
==31419== Use of uninitialised value of size 8
==31419== at 0x4E7F1CB: _itoa_word (in /usr/lib64/libc-2.17.so)
==31419== by 0x4E83450: vfprintf (in /usr/lib64/libc-2.17.so)
==31419== by 0x4E8A338: printf (in /usr/lib64/libc-2.17.so)
==31419== by 0x400561: main (sample2.c:9)
==31419== Uninitialised value was created by a stack allocation
==31419== at 0x40052D: main (sample2.c:4)
下面的完整检查消息:
==31419== Memcheck, a memory error detector
==31419== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==31419== Using Valgrind-3.14.0 and LibVEX; rerun with -h for copyright info
==31419== Command: ./sample2
==31419==
==31419== Conditional jump or move depends on uninitialised value(s)
==31419== at 0x4E81AFE: vfprintf (in /usr/lib64/libc-2.17.so)
==31419== by 0x4E8A338: printf (in /usr/lib64/libc-2.17.so)
==31419== by 0x400561: main (sample2.c:9)
==31419== Uninitialised value was created by a stack allocation
==31419== at 0x40052D: main (sample2.c:4)
==31419==
==31419== Use of uninitialised value of size 8
==31419== at 0x4E7F1CB: _itoa_word (in /usr/lib64/libc-2.17.so)
==31419== by 0x4E83450: vfprintf (in /usr/lib64/libc-2.17.so)
==31419== by 0x4E8A338: printf (in /usr/lib64/libc-2.17.so)
==31419== by 0x400561: main (sample2.c:9)
==31419== Uninitialised value was created by a stack allocation
==31419== at 0x40052D: main (sample2.c:4)
==31419==
==31419== Conditional jump or move depends on uninitialised value(s)
==31419== at 0x4E7F1D5: _itoa_word (in /usr/lib64/libc-2.17.so)
==31419== by 0x4E83450: vfprintf (in /usr/lib64/libc-2.17.so)
==31419== by 0x4E8A338: printf (in /usr/lib64/libc-2.17.so)
==31419== by 0x400561: main (sample2.c:9)
==31419== Uninitialised value was created by a stack allocation
==31419== at 0x40052D: main (sample2.c:4)
==31419==
==31419== Conditional jump or move depends on uninitialised value(s)
==31419== at 0x4E8349F: vfprintf (in /usr/lib64/libc-2.17.so)
==31419== by 0x4E8A338: printf (in /usr/lib64/libc-2.17.so)
==31419== by 0x400561: main (sample2.c:9)
==31419== Uninitialised value was created by a stack allocation
==31419== at 0x40052D: main (sample2.c:4)
==31419==
==31419== Conditional jump or move depends on uninitialised value(s)
==31419== at 0x4E81BCB: vfprintf (in /usr/lib64/libc-2.17.so)
==31419== by 0x4E8A338: printf (in /usr/lib64/libc-2.17.so)
==31419== by 0x400561: main (sample2.c:9)
==31419== Uninitialised value was created by a stack allocation
==31419== at 0x40052D: main (sample2.c:4)
==31419==
==31419== Conditional jump or move depends on uninitialised value(s)
==31419== at 0x4E81C4E: vfprintf (in /usr/lib64/libc-2.17.so)
==31419== by 0x4E8A338: printf (in /usr/lib64/libc-2.17.so)
==31419== by 0x400561: main (sample2.c:9)
==31419== Uninitialised value was created by a stack allocation
==31419== at 0x40052D: main (sample2.c:4)
==31419==
4195392
==31419== Conditional jump or move depends on uninitialised value(s)
==31419== at 0x400588: main (sample2.c:13)
==31419== Uninitialised value was created by a stack allocation
==31419== at 0x40052D: main (sample2.c:4)
==31419==
==31419==
==31419== HEAP SUMMARY:
==31419== in use at exit: 0 bytes in 0 blocks
==31419== total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==31419==
==31419== All heap blocks were freed -- no leaks are possible
==31419==
==31419== For counts of detected and suppressed errors, rerun with: -v
您有一个 64 位处理器。即使该值本身是 32 位,它也会在 64 位 register 中传递到 printf
;这来自 x86-64 的 System-V 调用约定。
但是它似乎直到后来才触发错误,此时 valgrind 似乎只知道该值被符号扩展为 64 位并且最初来自您的 main
函数(甚至是行那里的号码是错误的。
如果你用 -m32
编译它并设法在 valgrind 下 运行 它(我需要在 Ubuntu 上安装额外的 32 位包),你确实可以看到 4这里:
==4854== Use of uninitialised value of size 4
==4854== at 0x48A3CAB: _itoa_word (_itoa.c:179)
==4854== by 0x48A85C5: vfprintf (vfprintf.c:1642)
==4854== by 0x48AF2F5: printf (printf.c:33)
==4854== by 0x1085D0: main (sample2.c:9)
==4854==
==4854== Conditional jump or move depends on uninitialised value(s)
==4854== at 0x48A3CB3: _itoa_word (_itoa.c:179)
==4854== by 0x48A85C5: vfprintf (vfprintf.c:1642)
==4854== by 0x48AF2F5: printf (printf.c:33)
==4854== by 0x1085D0: main (sample2.c:9)
==4854==
这里要注意的一件事是 int
a[2]
中的值是不确定的,但是没有 int
类型的陷阱值并且它的地址被占用,因此将它传递给函数没有未定义的行为 - 但它在库函数中的使用却有。
我从博客中看到的 sample2.c 代码使用 valgrind 说明未初始化的值。这是代码: sample2.c:
1 #include <stdio.h>
2
3 int main()
4 {
5 int a[5];
6 int i,s;
7 a[0]=a[1]=a[3]=a[4]=0;
8
9 printf("%d\n",a[2]);
10 for(i=0;i<5;i++)
11 s += a[i];
12
13 if(s == 377)
14 printf("sum is %d\n",s);
15 return 0;
16 }
使用 gcc -g -o sample2 sample2.c
valgrind --leak-check=full --track-origins=yes ./sample2
我得到了下面的 valgrind 检查信息。
我不明白为什么在我的机器中由于 sizeof(int) == 4 而使用大小为 8 的未初始化值?我运行x64机器上的程序,所以这会是指针吗?
==31419== Use of uninitialised value of size 8
==31419== at 0x4E7F1CB: _itoa_word (in /usr/lib64/libc-2.17.so)
==31419== by 0x4E83450: vfprintf (in /usr/lib64/libc-2.17.so)
==31419== by 0x4E8A338: printf (in /usr/lib64/libc-2.17.so)
==31419== by 0x400561: main (sample2.c:9)
==31419== Uninitialised value was created by a stack allocation
==31419== at 0x40052D: main (sample2.c:4)
下面的完整检查消息:
==31419== Memcheck, a memory error detector
==31419== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==31419== Using Valgrind-3.14.0 and LibVEX; rerun with -h for copyright info
==31419== Command: ./sample2
==31419==
==31419== Conditional jump or move depends on uninitialised value(s)
==31419== at 0x4E81AFE: vfprintf (in /usr/lib64/libc-2.17.so)
==31419== by 0x4E8A338: printf (in /usr/lib64/libc-2.17.so)
==31419== by 0x400561: main (sample2.c:9)
==31419== Uninitialised value was created by a stack allocation
==31419== at 0x40052D: main (sample2.c:4)
==31419==
==31419== Use of uninitialised value of size 8
==31419== at 0x4E7F1CB: _itoa_word (in /usr/lib64/libc-2.17.so)
==31419== by 0x4E83450: vfprintf (in /usr/lib64/libc-2.17.so)
==31419== by 0x4E8A338: printf (in /usr/lib64/libc-2.17.so)
==31419== by 0x400561: main (sample2.c:9)
==31419== Uninitialised value was created by a stack allocation
==31419== at 0x40052D: main (sample2.c:4)
==31419==
==31419== Conditional jump or move depends on uninitialised value(s)
==31419== at 0x4E7F1D5: _itoa_word (in /usr/lib64/libc-2.17.so)
==31419== by 0x4E83450: vfprintf (in /usr/lib64/libc-2.17.so)
==31419== by 0x4E8A338: printf (in /usr/lib64/libc-2.17.so)
==31419== by 0x400561: main (sample2.c:9)
==31419== Uninitialised value was created by a stack allocation
==31419== at 0x40052D: main (sample2.c:4)
==31419==
==31419== Conditional jump or move depends on uninitialised value(s)
==31419== at 0x4E8349F: vfprintf (in /usr/lib64/libc-2.17.so)
==31419== by 0x4E8A338: printf (in /usr/lib64/libc-2.17.so)
==31419== by 0x400561: main (sample2.c:9)
==31419== Uninitialised value was created by a stack allocation
==31419== at 0x40052D: main (sample2.c:4)
==31419==
==31419== Conditional jump or move depends on uninitialised value(s)
==31419== at 0x4E81BCB: vfprintf (in /usr/lib64/libc-2.17.so)
==31419== by 0x4E8A338: printf (in /usr/lib64/libc-2.17.so)
==31419== by 0x400561: main (sample2.c:9)
==31419== Uninitialised value was created by a stack allocation
==31419== at 0x40052D: main (sample2.c:4)
==31419==
==31419== Conditional jump or move depends on uninitialised value(s)
==31419== at 0x4E81C4E: vfprintf (in /usr/lib64/libc-2.17.so)
==31419== by 0x4E8A338: printf (in /usr/lib64/libc-2.17.so)
==31419== by 0x400561: main (sample2.c:9)
==31419== Uninitialised value was created by a stack allocation
==31419== at 0x40052D: main (sample2.c:4)
==31419==
4195392
==31419== Conditional jump or move depends on uninitialised value(s)
==31419== at 0x400588: main (sample2.c:13)
==31419== Uninitialised value was created by a stack allocation
==31419== at 0x40052D: main (sample2.c:4)
==31419==
==31419==
==31419== HEAP SUMMARY:
==31419== in use at exit: 0 bytes in 0 blocks
==31419== total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==31419==
==31419== All heap blocks were freed -- no leaks are possible
==31419==
==31419== For counts of detected and suppressed errors, rerun with: -v
您有一个 64 位处理器。即使该值本身是 32 位,它也会在 64 位 register 中传递到 printf
;这来自 x86-64 的 System-V 调用约定。
但是它似乎直到后来才触发错误,此时 valgrind 似乎只知道该值被符号扩展为 64 位并且最初来自您的 main
函数(甚至是行那里的号码是错误的。
如果你用 -m32
编译它并设法在 valgrind 下 运行 它(我需要在 Ubuntu 上安装额外的 32 位包),你确实可以看到 4这里:
==4854== Use of uninitialised value of size 4
==4854== at 0x48A3CAB: _itoa_word (_itoa.c:179)
==4854== by 0x48A85C5: vfprintf (vfprintf.c:1642)
==4854== by 0x48AF2F5: printf (printf.c:33)
==4854== by 0x1085D0: main (sample2.c:9)
==4854==
==4854== Conditional jump or move depends on uninitialised value(s)
==4854== at 0x48A3CB3: _itoa_word (_itoa.c:179)
==4854== by 0x48A85C5: vfprintf (vfprintf.c:1642)
==4854== by 0x48AF2F5: printf (printf.c:33)
==4854== by 0x1085D0: main (sample2.c:9)
==4854==
这里要注意的一件事是 int
a[2]
中的值是不确定的,但是没有 int
类型的陷阱值并且它的地址被占用,因此将它传递给函数没有未定义的行为 - 但它在库函数中的使用却有。