Island Life

2008/08/25

デバッガ

未来のいつか/hyoshiokの日記

アプリケーションの開発時にはデバッガーを使うのはあたりまえだろう。 そのデバッガーを使えなくて何がプログラマだ、くらいの事は思うのだけど、 世のプログラミング言語の入門書にデバッグの仕方もましてやデバッガーの使い方も載っていない。

おごちゃんの雑文 - デバッガなんて使わねーよ

この手の言い草はよく聞くけれど、私はデバッガはほとんど使わない。使ってもせいぜい、どうしても他に資料のないコアダンプを解析しなきゃいけない時だけで、普段はまるっきり使わない。そこにソースがあるなら、怪しい箇所を推理しつつprintfをつっこむ。なぜなら、私はプログラムを書く時に一番大切なものは、そういったツールを使う能力ではなくて、

思考力

であると思うからだ。それと共に、本当にクリティカルなバグには、デバッガは無力だからでもある。

ハンドアセンブルが長かったので、CP/Mが動くようになってDDTという デバッガを最初に使った時は感動したものだ。ハンドアセンブルではprintfデバッグ は簡単ではない。コードを挿入するとアドレスがずれてジャンプオフセットの計算を やりなおさないとならない。インストラクションの頭をRST命令で潰すのが定石だが 戻し忘れると面倒なことになる。それを自動でやってくれて、対話的にレジスタの 内容が見られて、ステップ実行まで出来るというのは衝撃だった。 そのあとコアダンプを見るのにadbを覚えて、gdbを使うようになったのはだいぶ 後だなあ。一時期はgdb+Emacsで何でもやってた。

でも今ではデバッガは滅多に使わなくなった。使うときもソースレベルで ブレークポイント設定しまくってさらにステップ実行…というのはほとんどやらない。 インタラクティブな逆アセンブラ/メモリダンパとしての使い方が多いかなあ。 GC絡みの怪しい挙動の解析とか、最適化のかかったコードの振る舞いを追ったりとか、要するに ビットに直接触る必要がある場合限定。 通常のデバッグはprintfスタブを使い、もう少し込み入った問題であれば その問題限定の検証ツールを組み込んだりしている。

ソフトウェアって多くの層の積み重ねで、 gdbみたいなスタイルのデバッガがぴたっとサポートできるのは そのうちの特定の層だけなんだよね。 仕事の主要部分がその層に集中していればデバッガは強力な武器になるけれど、 そうでないとあまり役に立たない。で、昔はよく使ってたのに何で使わなくなったのか なあ、と考えてみたのだけれど、 ソースレベルデバッガは出発点としているモデル:「メモリ、レジスタ、 CPUの状態変化とソースとを関連付けて追っかける」っていうのが崩れてきているって 背景があるんじゃないかなあと。

  • ランタイムの多層化。例えばVM上で走るコードのロジックのバグの場合、 gdbで実行を追ってもVMの同じところをぐるぐる回ってるだけでほとんど何も分からない。 watchpointや条件付きbreakpointも、粒度がソースレベルのロジックと 大きく異なっていて使いにくい。
  • コンパイルタイムの多層化。 メモリ読み書きのリオーダリングで、ソースの字面どおりに状態が遷移することは もはや当てに出来なくなっている。高水準言語における「関数」や「データ構造」は 抽象的な存在で、そのまま一連のインストラクション列やメモリの連続した領域へと マップされることはどんどん減っている。
  • 単一の状態遷移モデルの限界。 並列に走ってるスレッドがあれば、ソースの字面で見えている状態遷移とは 関係ないところで状態が変わっちゃう。
  • あと、コードを実行する主体がもはやCPUとは限らない(GPU等)、とかね。

ソフトウェアの一番下が状態機械である以上、その層を覗くツールとしての 現在のスタイルのデバッガの有用性は今後も残るだろうけど、 より一般的なツールとしての「デバッガ」に求められる異なるモデルっていうのが 必要になってるんじゃなかろうか。状態遷移よりは静的・動的な検証というものが 主役になるような気がする。言語の方にもそれに結びついた仕様が入って行くだろうし。 というか大きな企業はこのくらい既に考えてるだろうから最近流行りの「えんたーぷらいず」 言語の開発環境にはそういう支援が入ってたりしないんだろうか。

Visual Studioで作業してる若い人なんかを見ていると、実行環境からすぐにデバッガに 入ってがしがし編集してすぐ再実行して…ってサイクルを回してて、それはそれで 悪くないんだけれど、何て言うのかな、 「手元のデバッガが面倒を見られる層に無意識的に作業リソースを集中させてしまう」 というおそれがあるようにも思う。無意識に「デバッガで見られる状態機械の レイヤを越えた抽象化を避ける」というか。杞憂ならいいんだけど。

(追記2008/08/27 01:56:39 PDT: ちなみに、もちろんロートルLisperは 「実行環境からすぐにデバッガに入ってがしがし編集してすぐ再実行」なんだけどさ。 20年前から。でももっと良いやり方があるんじゃないかなあ、と思うのだ。)

Tag: Programming

2008/08/20

らむ太とteapot

らむ太はなぜかUtah teapotがお気に入りで、画面にteapotが写ると大騒ぎする。 あんまり騒ぐのでかみさんがセコンドハンドショップで普通のティーポットを買って与えたら 喜んで遊んでいる。

CGアニメーションの特集番組でテクスチャマッピングか何かの説明で teapotが映り、ぐるっと一回りするシーンを見たらむ太は、 自分のティーポットを床に置くとそれを見ながら周囲を一周して 「おんなじ、おんなじ」と騒いでいた。 確かに、world coordinateでtransformするのと カメラ位置を(逆行列で)transformするので得られる映像は同じである。

らむ太語録

  • あわゆ (洗う)
  • たわいま (ただいま)

Tag: 生活

2008/08/12

rfc4180の曖昧性

CSV形式はRFC:4180でフォーマルに定められているのだが…

  • recordはCRLFで終わる、ただし最後のレコードの後ろのCRLFは省略可
  • recordはひとつ以上のfieldをCOMMAで区切ったもの

これって、ファイル末尾がCRLFで終わっている場合、

  1. それがrecord終端のCRLFなのか、
  2. その後ろにひとつの空のfieldを持つrecordがあって、その後ろのCRLFが省略されているのか、

わからないよなあ。

一応「各レコードのフィールド数は同じでなければならない」って規定があるから それまでに2つ以上のフィールドが出てきてれば(2)の可能性は排除できるけど。

まあ慣例的にはCRLFの後ろにEOFが来てればCRLFが終端だとするだろうけれど、 それを形式的に(EBNFとかPEGで)かつ簡潔に記述するのって結構面倒なような。

と、PEGのテスト用のCSVパーザをいじってて思った。

Tag: Programming

2008/07/31

病院の一日

一昨日昼前くらいに、らむ太の目の中にごみが入っているのをかみさんが見つけた。 白目の部分に0.5mmくらいの黒いものがくっついている。 eye washを買ってきて流そうとしてみたのだが、全く移動する気配がない。 そのうちeye washを嫌がってらむ太も散々泣いたんだが、それでも動かない。 見た感じ、真っ黒で表面はなめらか、周囲もスムースな円形の何かだ。 放っておくとそんなに気にするふうでもないのだけれど、 感染などすると心配なので午後からかかりつけのpediatricianに連れて行った。 ところがドクターもそれが何だかわからない。 (視線をじっと固定できずにきょろきょろするもんだからじっくり見られないってのもある。) 結局Kapiolani Hospitalの眼科を紹介してもらう。

で、昨日午前にまず眼科。瞳孔を開く薬を入れてまず眼の中を検査し、 何かが深く刺さっているのではないことを確認。Kapiolani Hospitalは産科と小児科が メインなので、さすがに子供の扱いには慣れている。 それでも、いざスワブで取り除こうとするとらむ太は散々暴れた。 目薬で表面麻酔を入れてるんだけど、やっぱり怖いらしい。 押さえつけてどうにかスワブで拭ってもらうが全然取れない。

結局、全身麻酔をかけて取り除くことになった。

全身麻酔となると色々おおごとになる。 かみさんはこのへんの知識があって、 麻酔前に食事が出来ないことを見越して朝食を抜いていたのが奏功。 午後には処置を受けられることになる。 食事のことを思い出させないようにひたすららむ太の気を惹いているうち、 本人も疲れたのだろう (緊張してハイテンションになっていたのもあるだろうが) 麻酔をかける直前に眠ってしまった。 それでも、静脈注入だったので針が入る時には起きて少し暴れたが 程なく大人しくなり、眼医者がピンセットで取り除いた。 回復室で眼を覚ますまで待って、結局丸一日潰れたが 無事に済んで何よりだ。

結局モノは何だったのかというと、虫であった。 顕微鏡を実家に置いてきてしまったので詳しくは見られないが、 何かの甲虫類っぽい。そいつがしがみついていた模様。

Tag: 生活

2008/07/25

環境設定メモ

サブマシン(Athron 64X2, socket 939)のオンボードGPUがしばらく前に壊れてしまった。 ビデオカードだけ挿そうにも、マザーボードの挿し口はPCIE、 手持ちのビデオカードはAGPのやつしかない。 で、置き換えを検討していたのだが、 新しめのマザボはどれもsocket AM2でDDR2になってしまっている。 どうせCPUとメモリまで総取っ替えするなら、もう6年使ってるメインマシンの方を変えたい。 ということで中身総取っ替え計画発動。メインマシンをCore2 Quad / DDR2 にして、 サブマシン用には壊れたマザボと同世代のやつ(ただしオンボードGPU無し、AGP、DDR)を 購入、メインマシンのビデオカードを流用することにした。サブのCPUとメモリも流用。

メインの新しいボードはSATAなので、HDDはIDE-SATAコンバータを介して接続。 さて、grubから/bootにあるカーネルを読むまではいいんだがlogical volumeが 見つけられないと申す(元のシステムはFedora8/i386)。Ubuntu 64のインストールCDで 立ち上げたらちゃんとlogical volumeも見えてマウントできるのに。もう面倒なので そのままUbuntuをインストールしてしまうことにする。

Ubuntu 7.10 x86_64 をCDからインストール。だいたいスムースに進む。 ただ、nvidiaのドライバがうまく動かないのと、オンボードether (Realtek 8111c) が認識されるにもかかわらずパケットが出てかない。

Update managerから8.04へとアップグレード。 localedefで刺さる問題に引っかかる。killall locale-genでインストールを通してから 古いカーネルでリブートしてdpkg --configure -aでOK。 8.04ではnvidiaドライバもオンボードetherもout of boxで使えた。

iptablesの設定がデフォルトでは何にも無いのだが、クライアント用途だからかな。 設定手書きも面倒くさいのでFirestarterを入れた。

XEmacsでトラブル。日本語を表示しようとすると落ちる。ぐぐるとx86_64でしばしば 見られる症状のようだが、解決法が見つからない。emacsに生活の大部分を依存している 身としてはemacsで日本語が使えないと話にならないので、たぶん10年以上慣れ親しんだ XEmacsから決別してGNU Emacsに乗り換えることにする。

んでemacs-snapshot (GNU Emacs 23.0.60.1)を入れてみたところ、mew (5.2) でメールを フェッチする際にArgument out of boundでエラーになることがある。 この問題っぽい。 原因となったasetの仕様については こちら。 文字列にunibyte stringとmultibyte stringがあって、unibyte stringに asetでASCIIレンジ外の文字をセットしようとするとout of boundエラーになると。 (こういう、ascii stringとそれ以外を区別することのあまりの煩わしさがGaucheを 作ることになった強い動機なのであった)。 この問題はmewのMLのスレッドを見るとより新しいemacsのHEADでは直っているっぽいが、 emacsをビルドするのも面倒なのでmewの方をいじって誤魔化した。

*** mew-header.el.orig  Fri Jul 25 11:26:36 2008
--- mew-header.el       Fri Jul 25 11:25:45 2008
***************
*** 276,282 ****
        (setq str (string-as-unibyte str))) ;; A bug of Emacs 20.7
      (let* ((i 0) (len (length str))
           (par-cnt 0) (tmp-cnt 0) (sep-cnt 0)
!          (tmp (make-string len ?x))
           c ret)

        (catch 'max
        (while (< i len)
--- 276,283 ----
        (setq str (string-as-unibyte str))) ;; A bug of Emacs 20.7
      (let* ((i 0) (len (length str))
           (par-cnt 0) (tmp-cnt 0) (sep-cnt 0)
!          ;(tmp (make-string len ?x))
!          (tmp (make-string len ?\x3030))
           c ret)
        (catch 'max
        (while (< i len)

バッファの文字列を無理やりmutibyte stringで作るだけ。

文字列をmutableなarrayと考えることについても大いに問題ありと思うが、 さすがにemacsくらい巨大なソフトになると簡単には変えられないだろうなあ。

Tag: PC

More entries ...