デバッグの方法

みなさんは、日ごろプログラミングにおいてデバッグはどのようにされているだろうか。Eclipse などの開発環境を使っている場合は、それを利用すればいいと思う。

しかし、私の長年の公私におけるプログラミングの経験では、開発環境はやはり栄枯盛衰がある。これまでで最も一貫性のある開発環境といえばマイクロソフトの Visual Studio となるだろう。また、Eclipse もこれから先の長いサポートが期待できそうであるが、プロたるもの、道具(Eclipse)は選ばないで仕事ができるようにしておくと何かと都合がよい。

それでは、最も基本的なデバッグ方法とは?かつ地味なデバッグ方法はプログラム中に print 文をはさんで変数の中身を出力していくことだ。

ここで、それぞれの print 文をデバッグコードと呼ぶことにするが、それぞれのデバックコードはインデントしないで常に行頭から書き始めるとよい。というのは、

ほとんどのプログラミング言語では

インデントをして人間が見やすくプログラムを書いているので、インデントしているさなかで行頭にデバッグコード(print 文)がいきなり出てくると、視覚的にもわかるし、あとでエディタで /^print/ といったように、行頭の print 文を探す正規表現で検索すれば、どこにデバッグコードを挟んだかすぐにわかるというメリットがある。

Perl なら Data::Dumper モジュールを利用して

#!/usr/bin/perl use Data::Dumper; $a = 'abc'; if(a eq 'abc') { print Dumper $a; # この行はデバッグコードだからあえてインデントしない $a = 'xyz'; print Dumper $a; # この行はデバッグコードだからあえてインデントしない } 1;

とすると、変数 $a の中身が変更前と変更後で文字通りダンプされてわかりやすい。

PHP は、通常は Perl と同じだが array の場合は少々やっかいで print_r を使う必要がある。

<?php $a = 'abc'; $b = array('a', 'b', 'c'); if($a == 'abc') { // $a が通常の変数 print $a; // この行はデバッグコードだからあえてインデントしない // $b が array の場合 print_r($b); // この行はデバッグコードだからあえてインデントしない $a = 'xyz'; $b[] = 'd'; // $a が通常の変数 print $a; // この行はデバッグコードだからあえてインデントしない // $b が array の場合 print_r($b); // この行はデバッグコードだからあえてインデントしない } ?>

である。

Java はオブジェクトの中身を調べるには少々気をつけなければならない。そのオブジェクトが toString() メソッドを実装しているなら、

Integer a = new Integer(123); if(a.intValue() == 123) { // ↓この行はデバッグコードだからあえてインデントしない System.out.println(a.toString()); a = new Integer(456); // ↓この行はデバッグコードだからあえてインデントしない System.out.println(a.toString()); }

とすればよい。

ほとんどのプログラミング言語では

と書いたのは、Python ではインデントによってブロックを表現しているため、文法上この方法が使えないからである。それをしてしまうと Python の場合はエラーとなってしまう。残念だ。。

また、デバッグコードは、単に変数の中身を出力するだけよりも、私は passed: という言葉を挟むようにしている。行頭のデバッグコードを正規表現で検索するよりも、実際は passed というキーワードで検索した方が早い。Perl、PHP、Java での例は以下の通り。

#!/usr/bin/perl $a = 'abc'; $b = 'xyz'; if($a eq 'abc') { print "passed 1: $a"; # この行はデバッグコードだからあえてインデントしない print "passed 2: $b"; # この行はデバッグコードだからあえてインデントしない $a = 'xyz'; $b = 'abc'; print "passed 3: $a"; # この行はデバッグコードだからあえてインデントしない print "passed 4: $b"; # この行はデバッグコードだからあえてインデントしない } <?php $a = 'abc'; $b = array('a', 'b', 'c'); if($a == 'abc') { // $a が通常の変数 print "passed 1: $a"; // この行はデバッグコードだからあえてインデントしない // $b が array の場合 print "passed 2:"; // この行はデバッグコードだからあえてインデントしない print_r($b); $a = 'xyz'; $b[] = 'd'; // $a が通常の変数 print "passed 3: $a"; // この行はデバッグコードだからあえてインデントしない // $b が array の場合 print "passed 4:"; // この行はデバッグコードだからあえてインデントしない print_r($b); ?> Integer a = new Integer(123); if(a.intValue() == 123) { // ↓この行はデバッグコードだからあえてインデントしない System.out.println("passed 1: " + a.toString()); a = new Integer(456); // ↓この行はデバッグコードだからあえてインデントしない System.out.println("passed 2: " + a.toString()); }

・・・と、こんなところだろうか。

C 言語の場合は、printf("%s", a); などとするが、型によって常に文字列が出力されるとは限らないことに注意。