はじめに
C言語の開発をする際、便利であるためにCodeSpaceを使用してしまいます。
CodeSpaceとは、古くは Visual Studio Codespaces が GitHub Codespaces と名前を変更させたのが遍歴のようで、名前の通りGitHub提供のクラウド版VisualStudioです。
クラウドであり複数のパソコンから接続することができ、作業中の環境をほとんど固定することができることから、普段から使わせていただいています。
さて、そんなCodeSpaceは、クラウドであるというのにほとんど癖を感じない点に強い魅力を覚えているのですが、それでもC言語の開発を行ってみるとすると、どうもシャープであったようで、困ることも多々あります。
今回はそんな事例。gdbでsegmentation faultについてのデバッグをしたいというのに、どうにもこうにも上手くいかなかったがために書き留めておきたい記事でございます。
ここまでなんとなく助長に文章を進めておいてなんですが、飽きたので文章量が減ります。
コアファイルサイズ
初期設定は0となっています。
ulimit -c
0
コアファイル出力先
初期設定では|/usr/share/apport/apportという場所を指しているようです。
そもそもapportが何かという話です。プログラムのエラーが発生したときに情報を収集し、自動でUbuntuの障害解析チームにレポートを送信するもののようです。デバッグ用にコアファイルが生成されるものではないようですので、これを変更したいです。
cat /proc/sys/kernel/core_pattern
|/usr/share/apport/apport -p%p -s%s -c%c -d%d -P%P -u%u -g%g -- %E
コマンド
コアファイルサイズが初期は0になっているのでunlimitedとします。
CodeSpace上でのコアファイルをリカレントディレクトリに出力させます。
sudo sysctl -w kernel.core_pattern="core"
ulimit -S -c unlimited
このターミナルコマンドを実行すると、core.-----というファイルが出力できるようになります。
gccもしくはg++でコンパイルの際に-gオプションを付け加え、実行ファイルを実行時にsegmentation faultが発生すると、コアファイルが生成されます。
デバッグ
コアファイルが生成されてから、gdbを使用してデバッグします。
core.-----の棒線部分は数字が入っているはずなので入力してください。
gdb ./a.out core.-----
gdbが起動されるとなんかいろいろと出てきますがわかんないのでスルーします。
バックトレースを行うとsegmentation faultが発生するまでの道筋が表示されます。
例えばこんな風。
(gdb) backtrace
#0 0x000055a23a4a1693 in function1 (n=0x55a23b827378) at main.c:331
#1 0x000055a23a4a1557 in function2 (w=1, n=0x55a23b827378) at main.c:309
#2 0x000055a23a4a1e8a in function3 () at main.c:461
#3 0x000055a23a4a0892 in main () at main.c:119
一番下の番号を指定して、より詳細にどこの地点でエラーが発生しているのかを判明させることができます。今回の場合は#3がそうです。
backtraceの長さによっては何十行という行数が出力されようという事もあり、その場合はenterやらcやら押して続きの文章を読んでください、というような英文が表示されると思うので、その指示に従って一番下のフレームまでたどり着いてください。
frame 3
#3 0x000055a23a4a0892 in main () at main.c:119
119 function3();
解釈するとソースコード上は119行目にあるfunction3という関数が原因である。ということのようです。それから必要に応じてローカル変数を参照することなどができます。さらに詳しいgdbの使い方は別の記事を参考にしてください。
私がよく参考にする分かりやすい記事を以下に貼らせていただきます。