wgetにおかしなヘッダを喰わせたら

MonaのMessageエミュレートのためにテストsocket プログラムを書いていたんですが、ちょっと間違った文字列のHTTPヘッダを送信したら怪しい動作をした。

colinux% wget --version
GNU Wget 1.10
colinux% wget http://127.0.0.1:2050
--14:27:03--  http://127.0.0.1:2050/
           => `index.html.5'
Connecting to 127.0.0.1:2050... 接続しました。
HTTP による接続要求を送信しました、応答を待っています... -1
wget: xmalloc.c:190: checking_free: Assertion `ptr != ((void *)0)' が失敗しました.
zsh: 2175 abort      wget http://127.0.0.1:2050

うは。怪しすぎる。xmalloc.cの中で落ちるってのは意図しない動作だろうなぁ。
これ結構やばそうなんで、調べようかなぁと思ったんですが
最新版(?)のwget 1.10.2を入れてみたらこの現象は起きなくなっていました。

関数型言語の勉強にSICPを読もう - (31) 3章 - 標準部品化力、オブジェクトおよび状態 (152ページ)

問題3.17

3日くらいずっと考えていた。

(define (count-pairs x)
  (let ((already? '()))
    (define (count-pairs-internal y)
      (let ((add-count 0))
        (if (not (pair? y))
            0
            (begin
              (if (not (memq y already?))
                  (begin (set! add-count 1) (set! already? (cons y already?)))
                  (set! add-count 0))
              (+ (count-pairs-internal (car y))
                 (count-pairs-internal (cdr y))
                 add-count)))))
    (count-pairs-internal x)))

;; 3
(define a (cons 'x (cons 'x (cons 'x 'x))))
(display (count-pairs a))
(newline)

;; 4
(define a (cons 'x 'x))
(define b (cons 'y a))
(define c (cons a b))
(display (count-pairs c))
(newline)

;; 7
(define a (cons 'x 'x))
(define b (cons a a))
(define c (cons b b))
(display (count-pairs c))
(newline)

最初から頭の中に正解に近いイメージがあったのだが、memqの引数を逆に渡しているのに気づかずはまる
あとは、add-countのスコープを1つ上にしてしまい、再帰的に書き換えられてはまる。
などなどの、はまりポイントをくぐったのでデバッグノウハウがたまりました。


※「SICPを読もう」の目次はこちら


計算機プログラムの構造と解釈
Gerald Jay Sussman Julie Sussman Harold Abelson 和田 英一
ピアソンエデュケーション (2000/02)
売り上げランキング: 56,404

関数型言語の勉強にSICPを読もう - (32) 3章 - 小休止 beginを利用した print デバッグについて

以前、traceを利用したデバッグ方法を紹介しました。
今日は begin を利用した print デバッグの方法を紹介します。

SICPを1ページ目から順に読んでいくと begin がなかなか出てこないのですが、今日 begin を知りこのデバッグ方法に気づきました。

例えば

(define (a)
  (let ((state 0))
    (define (b)
      (if (some-condition)
          (some-func)
          (else-func)
          )))
 たくさんの処理
)

のような手続きがあるとします。


このときに手続き b の戻り値は (some-func)か、(else-func)なのですが、(some-codition)を実行後に state の値を知りたい場合があると思います。
この場合 (display state)をどこかに挿入すればよさそうなのですが、if の中に隙がなさそうです。

でも begin を使えばこんなことができてしまいます。

(define (a)
  (let ((state 0))
    (define (b)
      (if (some-condition)
          (begin (display state) (some-func))
          (begin (display state) (else-func))
          )))
 たくさんの処理
)

beginは以下のような手続きです。

[R5RS] formを順に評価し、最後の値を返します。
Beginはletのような「ブロック」を作成するわけではありません。 すなわち、一般的にはform …の先頭に「内部のdefine (internal define)」を 置くことはできません。意味的には、beginはまるでform …が beginを囲むコンテクスト中に展開されているかのように振舞います。 例えば、トップレベルに次のような式があった場合、それは2つのトップレベルのdefineと 同等です


このように、値を返す部分であっても begin を使えば print デバッグができちゃいます。これは便利!。


ちなみに良く似た手続きで begin0 というものがありこれを利用すると同じことを

(define (a)
  (let ((state 0))
    (define (b)
      (if (begin0 (some-condition) (display state))
          (some-func)
          (else-func)
          )))
 たくさんの処理
)

と書けます。


もっと良い方法があるよなどご意見大歓迎です。

追記

Gaucheでは debug-printというマクロが用意されていてとてもよさげです。
コメントで教えていただきありがとうございました。


※「SICPを読もう」の目次はこちら


計算機プログラムの構造と解釈
Gerald Jay Sussman Julie Sussman Harold Abelson 和田 英一
ピアソンエデュケーション (2000/02)
売り上げランキング: 56,404

TSU-GCC製作記

面白い読み物。
大学の授業で作ったオリジナルCPUをターゲットとするGCCの製作記。
このようなものを大学3年のときにやるとは・・・。
TSU-GCC 製作記


じっと良く見てみたら、Min-Camlのid:sumiiさんだということに気づいてびっくり。
こういうのを読むと自分が足踏みばかりして前に進んでいないのではという気になってきますね。
気を引き締めてがんばろう。