6

私はコンパイルする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 を実行して、終了場所を確認することはできますか。

4

1 に答える 1

3

私はもともとコメントで答えました:

おそらくスタックオーバーフローを引き起こしています。スタックに「大きな」アレイを割り当てていますか?たとえばdouble myArray[10000000];、その場合は、とを使用してそのような割り当てをヒープメモリに置き換える必要がmallocあり freeます。

このようなスタックオーバーフローを意図的に引き起こし、valgrindが報告する内容を確認するために、短いcプログラムを作成しました。

#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

于 2012-09-27T15:19:48.117 に答える