LoginSignup
22
24

More than 1 year has passed since last update.

gdbでC/C++のデバッグ

Last updated at Posted at 2019-02-28

Segmentation fault (コアダンプ) の発生

CやC++を書いていると必ずといっていいほど悩まされるこのメッセージ
エラーの原因がterminalに直接出力されないので、初心者が躓きやすい所の1つです。

コアダンプの発生

Lambda:11	Em:1.01	ARI:0
Lambda:11	Em:1.02	ARI:0.290903
Segmentation fault (コアダンプ)

C++で書かれたクラスタリング(教師なし機械学習)を行うプログラムを実行中にSegmentation fault(コアダンプ)が発生。突如プログラムが停止してしまいました。
この原因箇所を突き止めるのにgdbというツールを使おうと思います。

gdbとは

GNUデバッガ(単にGDBとも)は、GNUソフトウェア・システムで動く標準のデバッガである。 これは、多くのUnix系システムで動作可能な移植性の高いデバッガであり、Ada、C言語、C++、FORTRAN、FreeBASICといったプログラミング言語に対応している。

gdbはUnixの標準的なCUIデバッガです。
eclipseやVisual StudioなどのIDEでは標準でGUIデバッガが使えるようになっていますが、目的はそれらのものと同様です。

使用方法

まずコンパイルオプションに「-g」を付けてコンパイルします。

g++ [ファイル名] -g -o

多くのLinuxディストリビューションではデフォルトでCoreDump機能が無効になっているため、有効にします。

ulimit -c unlimited

このコマンドの意味は生成するCoreのサイズを制限しないということです。

プログラムを実行します。

./a.out
...
(省略)
...
Lambda:11	Em:1.01	ARI:0
Lambda:11	Em:1.02	ARI:0.290903
Segmentation fault (コアダンプ)

ここでカレントディレクトリを見ると、「core」と名のついたファイルが生成されているはずです。
このcoreをGDBでデバッグしてみます。

gdb ./a.out core

GNU gdb (Ubuntu 8.1-0ubuntu3) 8.1.0.20180409-git
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./a.out...done.
[New LWP 10366]
Core was generated by `./a.out'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x00005599dc02eccb in Hcm::set_crispMembership (this=0x7ffcf0375ea0) at hcm.cxx:159
159	    CrispMembership[max_index][k]=1.0;

ここで一番下に原因となっている関数名が書かれています。

もっと詳しく見てみたいのでbacktraceします。

(gdb) backtrace
#0  0x00005599dc02eccb in Hcm::set_crispMembership (this=0x7ffcf0375ea0) at hcm.cxx:159
#1  0x00005599dc03c300 in main () at qfcma_main_user_knowledge.cxx:112

main関数の原因箇所を詳しく見たいので#1を指定します。

(gdb) frame 1
112	      test.set_crispMembership();

これでコアダンプの原因となった関数が特定できました。

必要に応じて原因箇所のコードを表示したり、ローカル変数を表示したりもできます。
詳しくは下記の記事を参照してください。

gdbについてのさらに詳しい記事

追記

今回のコアダンプの原因は、double型変数の計算限界によりNaNが発生し、配列に格納されたNaNを参照しようとした結果として配列外参照が起こっていたためでした。

22
24
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
22
24