c - 让 valgrind 显示常见错误

标签 c debugging valgrind

我使用 --track-origins=yes 运行 valgrind,所以我假设它会显示有关未初始化变量的错误,如下所示: valgrind --track-origins=是 ./指针 还可以在各种文件中永久编辑 valgrind 的设置吗?

我运行它的代码是这样的:

#include <stdio.h>
int main(){
   int age = 10;
   int height;
   printf("I am %d years old.\n");
   printf("I am %d inches tall.\n");

return 0;

}

这是我从 valgrind 得到的结果

==12005== Memcheck, a memory error detector
==12005== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==12005== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==12005== Command: ./pointer
==12005== 
I am -16776936 years old.
I am 2147483633 inches tall.
==12005== 
==12005== HEAP SUMMARY:
==12005==     in use at exit: 0 bytes in 0 blocks
==12005==   total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==12005== 
==12005== All heap blocks were freed -- no leaks are possible
==12005== 
==12005== For counts of detected and suppressed errors, rerun with: -v
==12005== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)

我期待这样的事情(来自“艰难地学习 c”)

==3082== Memcheck, a memory error detector
==3082== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
==3082== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info
==3082== Command: ./ex4
==3082== 
I am -16775432 years old.
==3082== Use of uninitialised value of size 8
==3082==    at 0x4E730EB: _itoa_word (_itoa.c:195)
==3082==    by 0x4E743D8: vfprintf (vfprintf.c:1613)
==3082==    by 0x4E7E6F9: printf (printf.c:35)
==3082==    by 0x40052B: main (ex4.c:11)
==3082== 
==3082== Conditional jump or move depends on uninitialised value(s)
==3082==    at 0x4E730F5: _itoa_word (_itoa.c:195)
==3082==    by 0x4E743D8: vfprintf (vfprintf.c:1613)
==3082==    by 0x4E7E6F9: printf (printf.c:35)
==3082==    by 0x40052B: main (ex4.c:11)
==3082== 
==3082== Conditional jump or move depends on uninitialised value(s)
==3082==    at 0x4E7633B: vfprintf (vfprintf.c:1613)
==3082==    by 0x4E7E6F9: printf (printf.c:35)
==3082==    by 0x40052B: main (ex4.c:11)
==3082== 
==3082== Conditional jump or move depends on uninitialised value(s)
==3082==    at 0x4E744C6: vfprintf (vfprintf.c:1613)
==3082==    by 0x4E7E6F9: printf (printf.c:35)
==3082==    by 0x40052B: main (ex4.c:11)
==3082== 
I am 0 inches tall.
==3082== 
==3082== HEAP SUMMARY:
==3082==     in use at exit: 0 bytes in 0 blocks
==3082==   total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==3082== 
==3082== All heap blocks were freed -- no leaks are possible
==3082== 
==3082== For counts of detected and suppressed errors, rerun with: -v
==3082== Use --track-origins=yes to see where uninitialised values come from
==3082== ERROR SUMMARY: 4 errors from 4 contexts (suppressed: 4 from 4)

最佳答案

一般来说,我认为不能保证 Valgrind 会检测到此类事情。如果获取但未传递的可变参数来自堆栈,则堆栈的该部分可能只是“意外”被初始化。

但是,在这种特殊情况下,您可能会看到 AMD64 ABI 的影响,而您引用的示例似乎是 x86(从地址不大于 32 位来看)。由于 AMD64 ABI 在寄存器中传递最多六个参数,因此 printf 甚至不会接触内存来获取参数,直到您提供更多参数为止。

例如,我尝试了这个程序:

#include <stdio.h>

int main(int argc, char **argv)
{
    printf("%i %i %i %i %i %i %i\n");
    return(0);
}

只有六个 %i 规范,Valgrind 不会发出任何警告,而如果有七个规范,我会收到警告。我相当确定这是因为参数在寄存器中传递。

(不过,我承认,我认为 6 个 %i 规范应该已经足够了,但是,考虑到格式字符串本身如何消耗一个寄存器。我不太清楚解释一下这种效果。除非,正如我上面提到的,第一个非寄存器参数恰好已在内存中初始化。)

关于c - 让 valgrind 显示常见错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21641333/

相关文章:

c - Libxml问题获取标签的属性

c - 从 C 文件中获取输入

c - C 中的位置换表

linux - 每小时 cron 作业未运行

c++ - 在任何事情发生之前程序在调试器中崩溃

arrays - Fortran 和 Visual Studio 调试中的自动数组长度

c++ - initializer_list 中的未初始化值(编译器错误?)

c - 最小化代码并获得相同的输出

c - 使用 valgrind 测试代码片段

c++ - 模板参数初始化