3

大規模なプログラムを作成しましたが、セグメンテーション違反を追跡するのに非常に苦労しています。質問を投稿しましたが、続行するのに十分な情報がありませんでした (以下のリンクを参照してください。もしそうなら、私はほとんど丸一日を費やして、コードの最小限にコンパイル可能なバージョンを再現するコードを考え出すのに何回も費やしたことに注意してください。エラーは無効です)。

https://stackoverflow.com/questions/16025411/phantom-bug-involving-stdvectors-mpi-c

だから今、私は初めてvalgrindを試しています。MPI(存在する場合)を考慮して特別なインストールを行わずに(単純に「sudo apt-get install valgrind」)インストールしました。ファイル名や行番号などの具体的な情報を期待しています (valgrind が変数名を提供することは不可能であることは理解しています)。を含む有用な情報を取得していますが、

  • サイズ 4 の無効な読み取り
  • 条件付きジャンプまたは移動は、初期化されていない値に依存します
  • 初期化されていない値がスタック割り当てによって作成されました
  • 1 ブロックの 4 バイトは確実に失われます

この魔法の物に加えて

  • syscall パラメータ sched_setaffinity(mask) は、0x433CE77 でアドレス指定できないバイトを指しています: syscall (syscall.S:31) アドレス 0x0 は、スタック、malloc、または (最近) 解放されていません

ファイル名と行番号を取得できません。代わりに、私は得る

==15095==    by 0x406909A: ??? (in /usr/lib/openmpi/lib/libopen-rte.so.0.0.0)

コードをコンパイルする方法は次のとおりです。

mpic++ -Wall -Wextra -g -O0 -o Hybrid.out (…file names)

valgrind を実行した 2 つの方法を次に示します。

valgrind --tool=memcheck --leak-check=full --track-origins=yes --log-file=log.txt mpirun -np 1 Hybrid.out

mpirun -np 1 valgrind --tool=memcheck --leak-check=full --track-origins=yes --log-file=log4.txt -v ./Hybrid.out

の指示に基づく 2 番目のバージョン

Open MPI で並列プログラムを実行するとセグメンテーション違反が発生する

選択した答えを正しく理解している場合、これは矛盾しているように見えます

valgrind を使用した openmpi (Ubuntu ディストリビューションで MPI を使用してコンパイルできますか?)

私は意図的に 1 つのプロセッサで valgrind を実行しています。これが、プログラムがセグメンテーション違反なしで完了するまで実行される唯一の方法だからです。また、2 つのプロセッサで実行したところ、予想どおりプログラム セグメント フォールトが発生しましたが、valgrind から返されたログには、本質的に同じ情報が含まれているように見えました。1 つのプロセッサで valgrind が報告する問題を解決することで、複数のプロセッサで発生している問題を魔法のように解決できることを願っています。

で提案されているように、プログラムのコンパイルに「-static」を含めようとしました

-g フラグがあるにもかかわらず、Valgrind が行番号を表示しない (Ubuntu 11.10/VirtualBox 上)

しかし、コンパイルは失敗し、(いくつかの警告に加えて)

dynamic STT_GNU_IFUNC symbol "strcmp" with pointer equality in '…' can not be used when making an executably; recompile with fPIE and relink with -pie

「fPIE」と「-pie」の意味を調べていません。また、私はメイクファイルを使用していないことに注意してください。また、現在、メイクファイルの書き方も知りません。

いくつかの注意事項: 私のコードでは、コマンド malloc、calloc、または new を使用していません。私は完全に std::vector; で作業しています。C配列はありません。.resize()、.insert()、.erase()、.pop_back() などのコマンドを使用します。私のコードは、参照と定数参照によってベクトルを関数に渡します。並列コマンドに関しては、MPI_Barrier()、MPI_Bcast()、および MPI_Allgatherv() のみを使用します。

valgrind が報告しているエラーのファイル名と行番号を表示するにはどうすればよいですか? ご協力ありがとうございました!

編集

私はそれに取り組み続けましたが、私の友人は、行番号のないレポートはすべてソースからコンパイルしていない MPI ファイルから来ていることを指摘しました。 、したがって、行は表示されません。というわけで、このコマンドを元にvalgrindを再試行したところ、

mpirun -np 1 valgrind --tool=memcheck --leak-check=full --track-origins=yes --log-file=log4.txt -v ./Hybrid.out

しかし、今は 2 つのプロセッサーの場合です。

mpirun -np 2 valgrind --tool=memcheck --leak-check=full --track-origins=yes --log-file=log4.txt -v ./Hybrid.out

プログラムは最後まで実行されました (コマンド ラインで報告されたセグ フォールトは表示されませんでした) が、この valgrind の実行により、ファイル内の行番号が表示されました。valgrind が指している行は、MPI_Bcast() を呼び出す行です。メモリの問題は複数のプロセッサでのみ発生するため、これが発生したと言っても過言ではありません (np -1 で正常に実行したため)。

4

1 に答える 1

0

間違ったツールを使用しているようです。セグメンテーション違反が発生した場所を知りたい場合は、gdb を使用します。

簡単な例を次に示します。このプログラムは、*b=5

// main.c

int
main(int argc, char** argv)
{
   int* b = 0;
   *b = 5;
   return *b;
}

gdb を使用して何が起こったかを確認するには; (<---- の部分は入力行の説明です)

svengali ~ % g++ -g -c main.c -o main.o # include debugging symbols in .o file
svengali ~ % g++ main.o -o a.out        # executable is linked (no -g here)
svengali ~ % gdb a.out
GNU gdb (GDB) 7.4.1-debian
<SNIP>
Reading symbols from ~/a.out...done.
(gdb) run <--------------------------------------- RUNS THE PROGRAM
Starting program: ~/a.out 

Program received signal SIGSEGV, Segmentation fault.
0x00000000004005a3 in main (argc=1, argv=0x7fffffffe2d8) at main.c:5
5      *b = 5;
(gdb) bt  <--------------------------------------- PRINTS A BACKTRACE
#0  0x00000000004005a3 in main (argc=1, argv=0x7fffffffe2d8) at main.c:5
(gdb) print b <----------------------------------- EXAMINE THE CONTENTS OF 'b'
$2 = (int *) 0x0
(gdb) 
于 2013-05-27T16:49:38.203 に答える