『Cプログラミング診断室』目次次(第11章 奇っ怪な条件 ずぼら)

第10章 最長不倒関数

デバッガ


最後に、ちょっとデバッグについて説明しましょう。 次のプログラム(リスト10−2)は正しいでしょうか。

リスト10−2 動的メモリ領域の破壊

     1  #include	<stdio.h>
     2  #include	<malloc.h>
     3  
     4  main()
     5  {
     6          char    *p;
     7  
     8          p = malloc( 8 );
     9          strcpy( p, "filename" );
    10          printf( "string=%s\n", p );
    11  }

コンパイルし、動作確認すれば、きっとたいていのコンピュータでは問題な く動作してしまうでしょう。だから、「正しい」と思うわけですが、実は致命 的なバグが入ったまま、とりあえず動いているのです。つまり、「うそ」なの です。

理由は分かりますか。mallocしたサイズが1文字分不足しているのです。文 字列の最後には、必ずヌルバイト(\0)が付加されています。strcpyで文字列コ ピーしたとき、最後のヌルバイトもコピーされます。したがって、mallocのサ イズが1バイト不足で、mallocで確保したメモリ領域の次の1バイトを破壊し ています。しかし、幸運というべきか不幸というべきか、事件にならずにすん でいます。

バグなのですが、動いてしまいました。困ったものです。ここで示した、何 の役にも立たないような小さなプログラムのときには動くのですが、大きなプ ログラム中で、もし次の1バイトをゼロクリアなんてしてしまったら、もう大 変です。何が起きるか分かったものではありません。次の1バイトを破壊した 瞬間に事件が起きれば原因は見つけやすいのですが、事件がおきるのは、破壊 されたバイト部分が参照された瞬間です。もうそのときには、いつ破壊された かも良く分からないでしょう。freeの瞬間に事件になれば、まだポインタある いはメモリ管理データが破壊されたからだと推測できます。

文字列用の配列を確保し、そこに配列サイズ以上の文字列をコピーしようと するとどうなるでしょうか。その例が次のリストです。

リスト10−3 隣接する局所変数の破壊

     1	#include        <stdio.h>
     2	#include        <malloc.h>
     3	
     4	main()
     5	{
     6	        char    p[8];
     7	        char    *str = "filename";
     8	
     9	        strcpy( p, str );
    10	        printf( "string=%s\n", p );
    11	        printf( "string=%s\n", str );
    12	}

マシンにより異なりますが、私が今、この原稿を書きながらチェックもして いるSUN4では、動作してしまいます。詳しく調べたら、8バイトの文字配列p の直後にポインタstrが確保されていました。したがって、strcpyで、ポイン タstrの最初の1バイトはゼロクリアされてしまい、最後のprintfで止まるは ずですが、ちゃんと動きます。それは、ポインタの最初の1バイトが元々0で、 0を書き込んでも何も影響しなかったからです。きわどい偶然で動作していた のです。

でも、このようなバグはぜひ見つけて取り除かなければ、いつ何時暴れだす やも知れません。

■CodeCenter

このような非常に取りにくい「潜在バグ」まで見つけてくれるデバッガがあ ります。その名を、CodeCenterと言い、もう頼 るものがなくなったとき、最後の望みをかなりかなえてくれるデバッガです。

最近、仕事上でMotifをよく使っているのですが、新バージョンに切替えた とたん、全然変な動作をするようになったのです。アプリケーションも何万行 もありますが、Motifのインクルードファイルとライブラリの変更だけで、今 まで動いていたものが突然動かなくなりました。当然新バージョンのバグが考 えられるのですが、dbxのような普通のデバッガでは全然直接の原因がつかめ ません。短いテストプログラムを組んでみたら、新バージョンでも動いてしま います。

「しかたがない!こうなったらCodeCenterだ」ということで、ついにバグが 発見できたところが次図です。

もちろん、Motifのライブラリのソースなど存在しませんが、エラー原因 が完璧に表示されています。中央付近に日本語でエラーメッセージが出ている でしょう。これによると、libXm.aというライブラリの中のオブジェクト XmString.oで、strcpyが使われていますが、8バイトしか確保していない領域 に9バイトの文字列をコピーしようとしていることが分かります。

もう完璧です。この画面のハードコピーを付けてメーカーに文句を言えば、 完全な証拠になるでしょう。CodeCenterがあれば、ソースリストがなくても、 開発者あるいは移植者以上のレベルでデバッグができてしまいました。

このバグは、OpenWare/Motif version2 SPARCシリーズのものです。雑誌連 載時にはまだバグがありましたが、最新版ではバグも取れ、ユーザ登録されて いる人のところには正常なものが再配布されていることでしょう。A???I社も CodeCenterのような強力なデバッガを使っていたら、こんなバグ入りで出荷す ることもなかったでしょう。

さすが、A???C社の日本の超トップレベルのUNIXハッカーが移植しただけあっ て、デバッグ性能は超強力です。難は、マニュアルがちょっと読みにくく、索 引がないので調べにくいことでしょうか。商品についてくるデモの部分のサン プルを参考にした方がマニュアルより分かりやすかったですね。それでも、こ のデバッグ支援能力は、まったく他の追随を許さないものがあります。


参考文献

[10-1] Programming perl, Larry Wall and Randal L.Schwartz, O'Reilly & Associates,Inc.
[10-2] CodeCenterチュートリアル、CodeCenterユーザーズ・ガイド、アステック
[10-3] OpenWare/Motif version2 ツールキットプログラマーズガイド、アスキー


Copyright1996 Hirofumi Fujiwara. No reproduction or republication without written permission
『Cプログラミング診断室』目次次(第11章 奇っ怪な条件 ずぼら)