程序使用 valgrind memcheck 提前终止

Posted

技术标签:

【中文标题】程序使用 valgrind memcheck 提前终止【英文标题】:Program terminates early with valgrind memcheck 【发布时间】:2012-09-27 15:01:27 【问题描述】:

我有一个我用它编译的 C 程序(很多数字而且太长无法发布)

gcc -g -O0 program.c -o program

我正在尝试使用 gdb 和 valgrind memcheck 对其进行调试。在对代码进行一些更改后,我发现

valgrind --tool=memcheck --log-file=output.log ./program

给予

==15866== Memcheck, a memory error detector
==15866== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==15866== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==15866== Command: ./program
==15866== Parent PID: 3362
==15866== 
==15866== Warning: client switching stacks?  SP change: 0xbe88bcd8 --> 0xbe4e1f70
==15866==          to suppress, use: --max-stackframe=3841384 or greater
==15866== Invalid write of size 4
==15866==    at 0x804B7BE: main (program.c:1396)
==15866==  Address 0xbe4e1f74 is on thread 1's stack
==15866== 
==15866== Invalid write of size 4
==15866==    at 0x804B7C2: main (program.c:1396)
==15866==  Address 0xbe4e1f70 is on thread 1's stack
==15866== 
==15866== Invalid read of size 4
==15866==    at 0x4320011: on_exit (on_exit.c:34)
==15866==    by 0x43064D2: (below main) (libc-start.c:226)
==15866==  Address 0xbe4e1f70 is on thread 1's stack
==15866== 
==15866== Invalid read of size 4
==15866==    at 0x4320022: on_exit (on_exit.c:37)
==15866==    by 0x43064D2: (below main) (libc-start.c:226)
==15866==  Address 0xbe4e1f74 is on thread 1's stack

还有更多类似的。

valgrind --tool=memcheck --max-stackframe=3841384 --log-file=output.log ./program

不打印任何错误。但令我困惑的是,两个 valgrind 调用程序都会提前退出(没有错误消息)并且不执行它应该执行的计算。具有相同编译器选项但在没有 valgrind 的情况下运行的行为完全不同,看起来很正常。但是我怀疑是内存错误,并想使用 valgrind 来查找它。因此,我的问题是:当使用 valgrind 执行程序时,什么样的错误会使程序变得如此不同?如果这些是与内存相关的错误,我该如何识别它?请注意,我很清楚我可以“手动调试”来定位它。但是我可以用 valgrind 运行 gdb 来查看它的退出位置吗?

【问题讨论】:

您可能导致堆栈溢出。您是否在堆栈上分配“大”数组?例如。 double myArray[10000000]; 如果是这样,那么您应该使用mallocfree 将此类分配替换为堆内存。 使用 valgrind 执行时,什么样的错误会使程序表现得如此不同? 未定义的行为。 你试过--leak-check=full吗? @Shahbaz 是的,我做到了。没有其他错误。 @Douglas 我认为你可能是对的。这种数组的一般限制是什么?我在一个结构中有几个(不是那么大的)。使用 malloc 分配结构会有所不同吗? 【参考方案1】:

我原来是在cmets中回答的:

您可能导致堆栈溢出。你在分配“大” 堆栈上的数组?例如。 double myArray[10000000]; 如果是,那你 应该使用malloc 将此类分配替换为堆内存,并且 free.

我写了一个简短的 c 程序来故意导致这样的堆栈溢出并检查 valgrind 报告的内容:

#include <stdio.h>

int main()

  // imax*sizeof(double) is too big for the stack.
  int imax = 10000000;
  double test[imax];

  // I do a little math to prevent the stack overflow from being optimized away if -O3 is used.
  test[0]=0;
  test[1]=1;
  for(int i=2; i<imax; i++)
    test[i]=0.5*(test[i-1]+test[i-2]);
  printf("%e\n", test[imax-1]);


果然valgrind想出了:

==83869== Warning: client switching stacks?  SP change: 0x104802930 --> 0xffbb7520
==83869==          to suppress, use: --max-stackframe=80000016 or greater
==83869== Invalid write of size 8
==83869==    at 0x100000ED0: main (in ./a.out)
==83869==  Address 0xffbb7520 is on thread 1's stack

连同大量其他错误消息,并最终以 Segmentation fault: 11 退出

【讨论】:

我没有看到 Segfault 的事实可能与我的程序捕获了一些信号有关。我会调查的。 @highsciguy 也试一试我发布的代码,以确保您在这种简单情况下看到 seg 错误。

以上是关于程序使用 valgrind memcheck 提前终止的主要内容,如果未能解决你的问题,请参考以下文章

Valgrind:致命错误:memcheck.h:没有这样的文件或目录

Valgrind

Valgrind无法在Android OS上执行memcheck工具?

valgrind 内存调试工具

valgrind memcheck xtree 文件的工具

是否有类似 Valgrind Memcheck 的工具,用于在出现免费错误后调试 Windows 使用? [关闭]