Diomidis Spinellis :Effective Debugging

いろいろ難しいデバッグ

作成日:2021-04-04
最終更新日:

概要

副題は「ソフトウェアとシステムをデバッグする 66 項目」。著者による本書の例のコードは下記にある。
http:/www.spinellis.gr/debugging/

感想

この本は、私には難しい。

1章

項目1

「項目1:あらゆる問題を課題管理システムで扱う」から、いきなりつまづいてしまった。 というのも、課題管理システムを私は使っていないからだ。しかたがない。自分でいれよう。 本書1ページには、オープンソースの課題管理システムとして、 Bugzilla、Lauchpad、OTRS、Redmine、Trac が列挙されている。

インストールの一部始終は課題管理システムというページに書いた。 私がインストールできたのは Redmine だ。この画面は次のようになる。

これを見るとわかるように、優先度は定義されているが、本書で重要だとされている「深刻度」と 影響を受ける「関係者」、バグが生じたときの「環境」の欄がない。運用では注意すべきだろう。

項目2

コード専門の検索エンジンがあるとは知らなかった。次のサイトがそうだ。
https://searchcode.com

賢い質問のしかたも確認しよう。
https://www.ranvis.com/articles/smart-questions.ja.html

項目3

数値が数学関数の定義域の範囲内であることを確かめる、とある。そういえば昔、会社の同僚に「バグをみつけてください」 とプログラムを見せられたことを思い出した。そのプログラムは科学技術計算を対話的に行うものだったから、 対数計算をするメニューでマイナスの値を入れてみたら異常終了するだろうと見当をつけて実行したら、 本当に異常終了した。

項目4

表題は「問題からバグをドリルアップするかプログラム先頭からバグへドリルダウンする」となっている。 ドリルアップやドリルダウンはデータ探索にときに使うことばなので抵抗があったが、 それはたいしたことではないだろう。

問題がエラーメッセージで明らかになっているなら、最初にメッセージ文をソースコードから探す。 (太字は本書の通り) というところで、検索したメッセージ文がソースコードに埋め込まれているのではなく、 地域化ファイルによって使われている事例が紹介されている。 地域化ファイルについては、全文検索エンジン Namazu についてまとめた資料のうち、 表示の多言語化という記事で少し勉強したのだった。

2章 汎用の手法と実践

項目12

複雑なテストシナリオを自動化することに焦点を当てている。Lua 言語が紹介されている。 Lua はソフトウェアに組みまれることを想定して設計された、ということは聞いていたが、 実際に Apache HTTP や Wireshark 、VLC メディアプレイヤーなどが Lua をサポートしているとは知らなかった。

私の環境ではどうだろうか。

$ lua

コマンド 'lua' が見つかりません。次の方法でインストールできます:

sudo apt install lua5.1     # version 5.1.5-8.1build4, or
sudo apt install lua5.2     # version 5.2.4-1.1build3
sudo apt install lua5.3     # version 5.3.3-1.1ubuntu2
sudo apt install lua50      # version 5.0.3-8build1
sudo apt install tarantool  # version 1.9.1.26.g63eb81e3c-1.1build3
$ sudo apt install lua5.3

インストールは成功した。

4章 デバッガ技法

デバッガは苦手だ。

項目28

p.74 では、デバッグビルドでは、最適化なしでビルドするようコンパイラを構成する。 と書かれている。最適化なしのビルドに関しては、次のページで、 コンパイラの最適化を防ぐには Unix では -O0 というオプションを使う、と書かれている。 本書では O と 0 の活字の区別をするとき、0 は O より少し背が低いので区別できるが、少し紛らわしい。

項目35

コアダンプの扱い方である。コアダンプサイズの上限は、しばしばゼロに設定されていることに注意する。 ということだ。私が使っている WSL2 Ubuntu 20.04 も ulimit -c でサイズを調べたら 0 だった。ということで、 .bashrc に ulimit -c unlimited と記載した。これでどうだろうか。

やはりコアファイルはカレントディレクトリにはない。/var/log/kern.log を見ると、こんな行がある。

	Apr 11 14:24:42 localhost kernel: [ 2307.036910] Core dump to |/usr/share/apport/apport pipe failed

他の方々のページを見ると、/var/log/apport.log を見てエラーを確認しているが、私の環境では /var/log に apport.log というログファイルがない。それでも、 次のような処置をすればコアファイルはできるだろうという見当はついた。

1. /etc/sysctl.conf ファイルに次の1行を加える:
kernel.core_pattern = core.%e.%p
2. /etc/default/apport を次のようにする。
#enabled=1
enabled=0

参考:

それで実行ファイルはできたのだが、サイズが0バイトである。
-rw-r--r-- 1 1000 1000 0 4月 11 15:00 core.fuzzme.1452

もちろん、ulimit -c は unlimited に設定している。なのに、サイズが0バイトとなった理由はわからない。 あきらめた。

5章 プログラミング技法

項目42

ユニットテストが述べられている。C++ では CPPUnit テストについて記載されている。 Ruby のユニットテストは本で見ていたが、C++ のユニットテストは知らなかった。 WSL2 の Ubuntu 20.04 に入れてみた。

6章 コンパイル時の技法

項目50

pp.129-130 の例を Visual Studio 2015 で試してみた。やはり同じようになる。

PS C:> cl t.c
Microsoft(R) C/C++ Optimizing Compiler Version 19.00.23026 for x86
Copyright (C) Microsoft Corporation.  All rights reserved.

t.c
t.c(3): error C2059: 構文エラー: '/'

p.130 の対応も同じようにうまくいった。

PS C:> cl /E t.c
Microsoft(R) C/C++ Optimizing Compiler Version 19.00.23026 for x86
Copyright (C) Microsoft Corporation.  All rights reserved.

t.c
#line 1 "t.c"

double toDegrees = 360 / 2 / 3.1415926535897932384626433832795;;
double toRadians = 2 * 3.1415926535897932384626433832795; / 360;
PS C:> cl /EP t.c
Microsoft(R) C/C++ Optimizing Compiler Version 19.00.23026 for x86
Copyright (C) Microsoft Corporation.  All rights reserved.

t.c


double toDegrees = 360 / 2 / 3.1415926535897932384626433832795;;
double toRadians = 2 * 3.1415926535897932384626433832795; / 360;

上は、オプション /E 、下はオプション /EP を指定した。上下の違いは、 上はソースファイルの行の位置を示す #line が指定されているのに対し、 下は #line が指定されていない。なお、下記の説明では、 /E と /EP の違いが説明されていない。

https://docs.microsoft.com/ja-jp/cpp/build/reference/compiler-options-listed-by-category?view=msvc-160

なお、本来ならこのような定数定義に #define を使うのは避けるべきで、
const double PI = 3.1415926535897932384626433832795;
とすべきものだ。

7章 実行時の技法

項目55 迅速に失敗させる

プログラムが失敗するのを早めるための方法が列挙されているが、次は知らなかった。 Unix シェルで -e オプションを使って、シェルスクリプトがエラー(非ゼロ終了状態) でコマンド終了した時に、強制終了させる。 使えるときに使いたい。

8章 マルチスレッドコードのデバッグ

項目60 デッドロックを事後検討デバッグで分析する

まず、C++ のコードでデッドロックが起きることを確かめた。コアダンプファイルはできたが、 サイズが 0 バイトだった。なぜこうなるのか、よくわからない。

仕方がないので、今度は Java のコードを試した。こんどは本の通りうまくいった。 当たり前のことだが、こんな感じだ。

$ ls
Deadlock.java Deadlock.class
$ java Deadlock
Hi, it's Bob 0
^Z
[1]+  停止                  java Deadlock
$ bg
[1]+ java Deadlock &
$ jps
129202 Deadlock
129402 Jps
$ jstack -l 129202
2021-04-11 09:51:11
Full thread dump OpenJDK 64-Bit Server VM (14.0.2+12-Ubuntu-120.04 mixed mode, sharing):
(中略)
Found one Java-level deadlock:
=============================
"Thread-1":
  waiting to lock monitor 0x00007f3594008e80 (object 0x00000000a4167560, a java.lang.Object),
  which is held by "Thread-0"

"Thread-0":
  waiting to lock monitor 0x00007f3594008d80 (object 0x00000000a4167550, a java.lang.Object),
  which is held by "Thread-1"

Java stack information for the threads listed above:
===================================================
"Thread-1":
        at Deadlock.lambda$main$0(Deadlock.java:10)
        - waiting to lock <0x00000000a4167560> (a java.lang.Object)
        - locked <0x00000000a4167550> (a java.lang.Object)
        at Deadlock$$Lambda$1/0x0000000800b78840.run(Unknown Source)
        at java.lang.Thread.run(java.base@14.0.2/Thread.java:832)
"Thread-0":
        at Deadlock.lambda$main$1(Deadlock.java:18)
        - waiting to lock <0x00000000a4167550> (a java.lang.Object)
        - locked <0x00000000a4167560> (a java.lang.Object)
        at Deadlock$$Lambda$2/0x0000000800b78c40.run(Unknown Source)
        at java.lang.Thread.run(java.base@14.0.2/Thread.java:832)

Found 1 deadlock.

誤植

Typo

p.226 の索引の左側、メモリ(memory)の小項目に、 「クラッシュ時点に生成されるのコアダンプファイル」とあるが、正しくは、 「クラッシュ時点に生成されるコアダンプファイル」だろう。

気になったことば

レジリエンスの訳注に「東北大震災」ということばがあるが、「東日本大震災」ということばを使うのがよりよいと思う。

書誌情報

書 名Effective Debugging
著 者Diomidis Spinellis
訳 者黒川 利明
技術監修石本 敦夫
発行日2018 年 3 月 22 日 初版第1刷
発行所オライリー・ジャパン
発売元オーム社
定 価3200 円(税別)
サイズ
ISBN978-4-87311-756-0
その他越谷市南部図書室で借りて読む
NDC

まりんきょ学問所コンピュータの部屋コンピュータの本品質保証 > Diomidis Spinellis:Effective Debugging


MARUYAMA Satosi