デバッグ
このページはバグレポートに関連する情報を集める方法を主題にしています。"デバッグ"という言葉を使ってはいますが、開発においてプログラムをデバッグする方法を解説するガイドではありません。
目次
アプリケーションが落ちる場合
コマンドラインから実行
アプリケーションが突然クラッシュしたときは、ターミナルエミュレータからアプリケーションを実行してみてください。小文字でアプリケーションの名前を入力します。パッケージの名前しか分からず、アプリケーションの実行可能ファイルの名前を知らない場合、以下のコマンドを実行することで実行可能ファイルの名前を確認できます。packagename はパッケージの名前に置き換えてください:
for f in `pacman -Ql packagename | grep "/bin/" | cut -d" " -f2`; do file $f 2>/dev/null | grep -q executable && basename $f; done
コアダンプが利用可能か確認
コアダンプは、プロセスが予期せず終了した時のプロセスのアドレス空間 (メモリ) の内容を記録したファイルです。アプリケーションがデバッグしやすい方法でコンパイルされている場合、どこで上手く動作しなくなったのかを見つけ出すためにコアファイルを使うことができます。
コアダンプの場所はオペレーティングシステムの設定によって異なることがあります。システムでコアダンプの出力が有効化されているかどうか、そしてそれがどこに出力されるかを見つけるには、コアダンプを見てください。
セグメンテーション違反
何が間違っているのか見つけ出すのに使用できるテクニックがいくつかあります。鹿撃ち帽をかぶりましょう。
Gdb
gdb は古典的で十分テストされたデバッグ用アプリケーションです。appname をデバッグしたい実行可能ファイルの名前に置き換えてください:
$ gdb appname r (wait for segfault) bt full
出力を Pastebin クライアントに投稿して URL をバグレポートに含めてください。
gdb の出力を改善する
まず -g, -O0, -fbuiltin フラグを付けて問題のアプリケーションをリコンパイルしてください。PKGBUILD の options に "!strip" があることを確認して、パッケージをインストールして上述のように gdb を再度実行します。
options 行は以下のようになります:
options=('!strip')
-g, -O0, -fbuiltin を有効にするには PKGBUILD の build() 関数の一番始めに以下の二行を記述します:
export CFLAGS="$CFLAGS -O0 -fbuiltin -g" export CXXFLAGS="$CXXFLAGS -O0 -fbuiltin -g"
フラグの意味は次のとおりです: -g はデバッグシンボルを有効にして -O0 は最適化を無効にします (-O2 が最もよく使われる最適化レベルです。-O3 は過剰 で -O4 以上は -O3 と全く同じ です)。
"core" ファイルが存在する場合、gdb と一緒に使うことでバックトレースを取得できます:
$ gdb appname core bt full
Valgrind
インライン展開された関数が無く strip されていないバイナリであるならば、大抵の場合 valgrind を使ってそのプログラムを実行することもよいアイデアといえます。valgrind は CPU をエミュレートし、大抵の場合、どこでおかしくなったかを表示したり、gdb に加えてさらなる情報を提供してくれるツールです。
$ valgrind appname
プログラムがクラッシュした場合、これによって多くの有益なデバッグ出力が得られます。さらに詳しい情報を得るには -v
と --leak-check=full
を使うとよいでしょう。
または、次を使います:
$ valgrind --tool=callgrind appname
そして、kcachegrind を使って出力ファイルを実行し、プログラムが使っている関数を視覚的に調査します。プログラムがハングした場合、これによって問題箇所の特定が楽になります。
欠けているファイルやライブラリ
Strace
strace はアプリケーションが実際に何をしているのかを細かく調査します。アプリケーションが存在しないファイルを開こうとしていた場合、strace でそのことを発見できます。
appname という名前のプログラムが開こうとしたファイルを調査するには:
$ strace -eopen appname
出力を保存して、Pastebin クライアントに投稿して URL をメモしてください。
LD_DEBUG
LD_DEBUG=files
を設定することでアプリケーションがどのようなファイルを必要としているのか確認できます。例えばアプリケーションの名前が appname の場合:
LD_DEBUG=files appname > appname.log 2>&1
出力は appname.log
に書き込まれます。
詳しくは ld-linux(8) を見てください。
Readelf
アプリケーションを実行した時に "no such file or directory" と表示される場合は、次のコマンドを実行してみてください (/usr/bin/appname
は実行可能ファイルの場所に置き換えてください):
$ readelf -a /usr/bin/appname | grep interp
インタプリタ (/lib/ld-linux-x86-64.so.2 など) が存在することを確認してください。必要であれば AUR から ld-lsb をインストールしてください。
C や C++ ではなく Python で書かれている場合
実行ファイルに対して file を使って情報を取得してください ("appname" は実行ファイルに置き換えてください):
$ file /usr/bin/appname
"ELF" と出力される場合、ファイルはバイナリ実行ファイルであり、大抵は C あるいは C++ などで書かれています。"Python script" と出力される場合、Python で書かれたアプリケーションです。
シェルスクリプトの場合、テキストエディタでシェルスクリプトを開いて実際に呼ばれるアプリケーション (ELF ファイル) の名前がないか確認してください (大抵はファイルの末尾に存在します)。シェルスクリプトの中で実行ファイルの名前の前に "gdb" を追加することでデバッグできます。gdb については上のセクションを参照してください。実行ファイルが引数を必要とする場合はコマンドの前に gdb --args
を付けます。
純粋なシェルスクリプトの場合、bash -x script_name
や bash -xv script_name
でデバッグすることが可能です。
Python アプリケーションの場合、クラッシュが発生した行番号やファイルなどが出力されます。Python に精通しているのであれば、修正できるか試してみてバグレポートに修正内容を加えても良いでしょう。
バグの報告
バグは https://bugs.archlinux.org に報告してください。さらにアプリケーションの開発者に直接報告して、Arch Linux のバグレポートにリンクを張っても良いでしょう。
ただし、パッケージングとは無関係の問題がアプリケーション自体に何かあると考えられる場合、上流 (アプリケーションの開発者) に直接バグを報告してください。基本的に、ソフトウェアは開発者からパッケージ作成者・メンテナを介してユーザーに届けられます。上流とはアプリケーションの開発者を示します。