いろいろ難しいデバッグ
副題は「ソフトウェアとシステムをデバッグする 66 項目」。著者による本書の例のコードは下記にある。
http:/www.spinellis.gr/debugging/
この本は、私には難しい。
「項目1:あらゆる問題を課題管理システムで扱う」から、いきなりつまづいてしまった。 というのも、課題管理システムを私は使っていないからだ。しかたがない。自分でいれよう。 本書1ページには、オープンソースの課題管理システムとして、 Bugzilla、Lauchpad、OTRS、Redmine、Trac が列挙されている。
インストールの一部始終は課題管理システムというページに書いた。 私がインストールできたのは Redmine だ。この画面は次のようになる。
これを見るとわかるように、優先度は定義されているが、本書で重要だとされている「深刻度」と 影響を受ける「関係者」、バグが生じたときの「環境」の欄がない。運用では注意すべきだろう。
コード専門の検索エンジンがあるとは知らなかった。次のサイトがそうだ。
https://searchcode.com
賢い質問のしかたも確認しよう。
https://www.ranvis.com/articles/smart-questions.ja.html
数値が数学関数の定義域の範囲内であることを確かめる、とある。そういえば昔、会社の同僚に「バグをみつけてください」 とプログラムを見せられたことを思い出した。そのプログラムは科学技術計算を対話的に行うものだったから、 対数計算をするメニューでマイナスの値を入れてみたら異常終了するだろうと見当をつけて実行したら、 本当に異常終了した。
表題は「問題からバグをドリルアップするかプログラム先頭からバグへドリルダウンする」となっている。 ドリルアップやドリルダウンはデータ探索にときに使うことばなので抵抗があったが、 それはたいしたことではないだろう。
問題がエラーメッセージで明らかになっているなら、最初にメッセージ文をソースコードから探す。
(太字は本書の通り)
というところで、検索したメッセージ文がソースコードに埋め込まれているのではなく、
地域化ファイルによって使われている事例が紹介されている。
地域化ファイルについては、全文検索エンジン Namazu についてまとめた資料のうち、
表示の多言語化という記事で少し勉強したのだった。
複雑なテストシナリオを自動化することに焦点を当てている。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
インストールは成功した。
デバッガは苦手だ。
p.74 では、デバッグビルドでは、最適化なしでビルドするようコンパイラを構成する。
と書かれている。最適化なしのビルドに関しては、次のページで、
コンパイラの最適化を防ぐには Unix では -O0 というオプションを使う、と書かれている。
本書では O と 0 の活字の区別をするとき、0 は O より少し背が低いので区別できるが、少し紛らわしい。
コアダンプの扱い方である。コアダンプサイズの上限は、しばしばゼロに設定されていることに注意する。
ということだ。私が使っている 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バイトとなった理由はわからない。 あきらめた。
ユニットテストが述べられている。C++ では CPPUnit テストについて記載されている。 Ruby のユニットテストは本で見ていたが、C++ のユニットテストは知らなかった。 WSL2 の Ubuntu 20.04 に入れてみた。
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;
とすべきものだ。
プログラムが失敗するのを早めるための方法が列挙されているが、次は知らなかった。
Unix シェルで -e オプションを使って、シェルスクリプトがエラー(非ゼロ終了状態)
でコマンド終了した時に、強制終了させる。
使えるときに使いたい。
まず、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.
p.226 の索引の左側、メモリ(memory)の小項目に、 「クラッシュ時点に生成されるのコアダンプファイル」とあるが、正しくは、 「クラッシュ時点に生成されるコアダンプファイル」だろう。
レジリエンスの訳注に「東北大震災」ということばがあるが、「東日本大震災」ということばを使うのがよりよいと思う。
書 名 | Effective Debugging |
著 者 | Diomidis Spinellis |
訳 者 | 黒川 利明 |
技術監修 | 石本 敦夫 |
発行日 | 2018 年 3 月 22 日 初版第1刷 |
発行所 | オライリー・ジャパン |
発売元 | オーム社 |
定 価 | 3200 円(税別) |
サイズ | 版 |
ISBN | 978-4-87311-756-0 |
その他 | 越谷市南部図書室で借りて読む |
NDC |
まりんきょ学問所 > コンピュータの部屋 > コンピュータの本 > 品質保証 > Diomidis Spinellis:Effective Debugging