2020-04-19

"DEBUG HACKS" 吉岡弘隆/大和一洋/大岩尚宏/安部東洋/吉田俊輔 著

コンピュータ業界の格言に「プログラムは思った通りではなく、書いた通りに動く。」というのがある。そして、「思った通り = 書いた通り」を定式化するのは自分自身!何事も思い通りになった時の快感ときたら... これが忘れられなくて、今日もプログラムを書く。まるで麻薬!プログラムを書くのは楽しい。おいらはプログラマではない。でも楽しい...

デバッグの基本姿勢に、状態を見る!ということがある。まずは観ること!これは科学的思考の基本中の基本だ。しかしながら、自分自身を客観的に見ることほど辛いものはない。自分で仕掛けておきながら、自ら姑チェック!なんとも自虐的な世界。
そこには、自己矛盾が多分に含まれる。自分は天才かもしれない!って思うこともある。年に一度や二度は。一方で、つまらないミスで時間を浪費する自分に向かって、バカヤロー!って叫ぶのはほぼ毎日ときた。それでも、真に思い通りになった時の征服感ときたら... 出来の悪い子ほど可愛いと言うが、苦労に苦労を重ねて作り上げたコードほど愛着がわく。自己啓発とは、自己陶酔の類いか。そして、再々々々... 認識させられるのである。自分自身がいかにアホウであるかを。踊る阿呆に見る阿呆、同じ阿呆なら踊らにゃ損々... やはりプログラムを書くのは楽しい...

プログラムを書くのは実に愉快。しかしながら、デバッグ作業は辛い。動作が明らかにおかしな時は些細なミスであることが多く、バグも可愛いもの。だが、深刻な問題になりがちなのは微妙に動いている時で、数十時間に一度落ちたり、再現しなかったり、この手のバグの憎らしさときたら。
ちなみに、「バグ」の語源は定かではないが、リレー式計算機の中に紛れ込んだ蛾が誤動作の原因になった事例があるそうな。その蛾は、後に COBOL の開発者となるグレース・ポッパー女史の日記に記念として貼り付けられたと聞く。そういえば、むかーし、おいらが所属していた研究所にネズミホイホイが置いてあった。社内伝説によると、ネズミが電線をかじってシステムダウンし、大騒ぎになった事例があったとか...
バグってやつは、思わぬところに潜んでやがる、実に多種多様な生物。実際、設計作業より検証作業の方がコストは高い。テスト駆動開発(TDD)という考え方もよく耳にするが、そんな小難しい用語は別にして、上流工程からテスト方法を具体的に考慮することが習慣になっている。それだけ痛い目に遭ってきたということか。プログラムの書き方はコーディングルールで規定することができても、バグの在り方を規定することはできない。こいつに対処する最善の方法は、自分で編みだすしかあるまい。常に改善の意識を怠らず...
「デバッグという作業はプログラマが 10 人いれば 10 通りのデバッグ方法があるかのような極めて属人的な作業です。そして、デバッグの達人もいれば、そうでない人もいる。軽やかに、それこそ鼻歌まじりに魔法のようにバグを見つけ出し、直すハッカーもいます。」

本書は、主に C/C++ の使い手や Linux カーネル開発者を対象とし、Linux 上で動くアプリケーションや、Linux カーネルそのものを話題にしている。おいらがカーネルを書くことはないだろう、おそらくこれからも... ただ覗くのは大好き。低水準のデバッグでは、x86/x64 アーキテクチャやアセンブラ言語の基礎知識も要請してくる。お馴染みの GDB も登場。おいらはハードウェア設計者だが、低水準のデバッグは必要不可欠なので、うってつけの教材かもしれない。
多くのツールを紹介してくれるのもありがたい。達人ともなると、使う道具からして違うようだ。気の利いたところでは、システムコールをトレースする strace、動的解析ツール Valgrind、カーネル情報を取得する kprobes/jprobes など。
興味深いところでは、Linux 環境では定番の oprofile によるプログラムの性能調査。あるいは、KAHO(Kernel Aided Hexadecimal code Operator)というやつを使って、コンパイラによって Optimaized out された変数の値を取得する事例が紹介される。要するに、関数単位で動的に置き換えることができるもので、デバッグ用関数を埋め込む仕掛けを伝授してくれる。最初から関数にデバッグモードを埋め込むというやり方もあるが、リアルタイムシステムでは悩ましいところ。
また、Linux には、システムのメモリ・スワップを使い尽くすと、メモリを確保する最終手段として、プロセスにシグナルを送信し、強制終了させる機能が装備されている。OOM Killer(Out of Memory Killer)が、それだ。これに関する proc ファイルシステムを解説してくれるが、"/proc/meminfo" や "/proc//mem" を覗くだけでも、かなりの情報が得られるだろう。もちろん、Linux カーネルのオプションとして提供されるフォルトインジェクションも見逃せない。

ちなみに、おいらは、プログラミング言語を学ぶならアセンブラ言語から始めるのがいいと考えるネアンデルタール人だが、そんな時代でもあるまい。スクリプト言語が活況な今日では、C言語系をいじるのも億劫だが、関数とマクロの物理構造がイメージできるかどうかは大きな違いがある。
コアダンプの景色も直接関わらなければ、なかなかの眺め!痕跡をセピア色に彩り、デスクトップの背景に貼り付けるのも一献。
今となっては、malloc() の呪いも妙に懐かしい。
Linux も随分と行儀よくなったもので、あの忌まわしいメッセージもとんと見かけなくなった。そこで、わざと発生させてみるのも一献... Kernel Panic !
昨今、プログラミング言語そのものが注目されがちだが、本書は、言語とデバッグを表裏一体の方法論として捉えているのがいい。デバッグという分野は、なかなかハウツー本にはできない。ブレークポイントの設定、ステップ実行、バックトレース、はたまたスタックやレジスタの表示、変数の監視など、やる事は定式化できても、いかに効率的にやるかとなると経験がモノを言う。達人ともなれば、それだけ失敗の経験も豊富のようだ。その意味で、本書は失敗から学ぶ良い事例集と言えよう。失敗の効率化という日頃の意識が、デバッグの達人を育てるらしい...

0 コメント:

コメントを投稿