恐怖! 64bitと0と可変長引数の組み合わせ

9月 8th, 2012

32bit用に書かれたC++のプログラムを
64bit環境で動かそうとした時にハマったのでメモ。

void GetParam(const char* key, int size, ...) { ... for (int i = 0; i < size; ++i) { int* var = va_arg(va, int*); if (var) *var = values[i]; } ... } ... GetParam("foo", 4, &bar, 0, &baz, 0); // ここでsegmentation fault ...

上記のプログラムを動かしたらsegmentation faultで死んでしまいました。
if (var) *var = values[i]; のあたりが怪しいと目星をつけて調べてみると、
なんということでしょう。varの値が0であると期待している箇所で、
0x7fffffff00000000といういかにも怪しい値が入っていました。

恐らく、可変長引数を使っているため、コンパイラは引数の型が分からず、
0を32bitの整数として扱ってしまったのでしょう。
0をNULLに書き換えたら無事動きました。

「C++ではNULLと0は等価」だと思っていたのですが、
少なくても可変長引数が絡んでくる場合は異なるようです。恐ろしや。

リリカルLispの開発がより容易になりました

8月 18th, 2012

結論

リリカルLispにテストコードを追加しました。
本編の練習問題のプログラムが正しく動作するか確認できます。
これで皆さんも、気軽にリリカルLispのソースがいじれますね。

背景

リリカルLispのソース、特にインタプリタの内部に手を加える時はそれなりに気を使う必要があり、
手を加えた後はちゃんと動くかどうか手でテストする必要がありました。
最低限、本編で出てくる練習問題のプログラムがちゃんと動作する
(正しいプログラムを入力した際に正解扱いされる)ことを確認する必要がありますが、
何回も手でプログラムを入力して確認するのはあまりにも面倒すぎます。
そんな訳で、練習問題のプログラムがちゃんと動作するか確認するテストを書きました。

この変更のためのコミットを(NScripterを読める人が)見れば分かることですが、
ラベル名を変数に入れてジャンプをするコードを多用しているため、
このテストと練習問題周辺のコードはとてつもなく可読性が落ちました。
まあ、インタプリタの周りを触る頻度に比べ、
練習問題の周りを触る頻度は遥かに少ない(と信じている)ので、
きっと問題ないでしょう。多分。

リリカルLispのソースのライセンス

5月 29th, 2012

前エントリ

tokumei より:
2012年5月28日 6:29 AM
>githubで公開しても、誰もメンテしてくれないしね。
どのファイルにもライセンスが書いてない(気がする)のでgithubでのforkすら躊躇ってしまう・・・・・・
ファイルは全部BSDLなんでしょうか?

という、もっともなコメントが付いたので、
githubにLICENSEを追加しました。
見ての通りの修正BSDライセンスですので、気軽にforkしてください。

リリカルLisp ver1.6

3月 29th, 2012

リリカルLisp ver1.6を公開しました。
約7ヶ月ぶりの更新です。

今回の変更点は高速化です。
今まで評価した引数をリストにつないでいた(いわゆるevlisを使っていた)ものを、
スタックに積む(つまり普通の手法)ものに書き換えました。
速さと引換に伝統的なLispインタプリタらしさが失われた感じです。
ちなみに、環境はいまだに連想リストで表現しているので、まだまだ速くできます。

ベンチマークとしてfib関数
(define(fib n)(if (<= n 1)1(+(fib(- n 1))(fib(- n 2)))))
(fib 12) を評価したところ、以下のような結果となりました。

バージョン 実行時間(秒) GC回数
1.5 55.855 3
1.6 46.512 1

ヒープへのアロケーションが減った結果、GC回数が削減され、実行時間も短縮されました。
GCが発生しないプログラムでも速くなる(ことがある)ことを確認しています。

何でもかんでもスタックに置くと、apply関係で面倒な事もあるのですが、
まあ、リリカルLispで非常に長いリストを作ることもないだろうと考え、
特に工夫はしないことにしました。

--

リリカルLispを作り始めたのは、私zickが学部1回生のときですが、
気がつけば修士2回生になっており、この3月で学生生活も終わりです。
今後どうなるかはわかりませんが、
可能な範囲でリリカルLispのメンテは続けていこうと思います。
githubで公開しても、誰もメンテしてくれないしね。

今年1年を振り返る 2011

12月 31st, 2011

適当に今年の出来事を10個集めてみました。
リンク先には一部、(あまり)関係の無いものが含まれています。

リリカルLispを色々アップデートした
コードを整理したり、起動時間を大幅に短縮したり、エラーのための処理を書いたりしました。

新・ニコ動でLispを作った
ニコスクリプト(ニワン語?)の仕様が変わって、かつて書いたものが動かなくなったので、書き直しました。

琵琶湖をPostScriptで描いた
今年も自転車で琵琶湖を回りました。しかし体力の配分を失敗して酷い感じに。悔しさを紛らわすためにPostScriptで遊びました。

WiLiKiを改造して遊んだ
WiLiKiを改造して遊びました。Gaucheが想像以上に何でも揃っていて感動。

観鈴ちんの誕生日なのでBiwaSchemeでゲーム作った
BiwaSchemeで簡単なゲームくらいなら、すぐに書けるようになりました。

Kashiwa Schemeを作っている
Lisp/Schemeのインタプリタは何度も書いてきましたが、コンパイラを書くのは実は初めてでした。

Dart勉強した
「Dart面白くない」という意見を多数聞いたので、あえてDartの勉強をしてみました。暇ができて実行環境が安定してきたら、もう少し変なことをやってみたいです。

LispギャグAdvent Calendar作った
大変でした。完成したのは本当に皆さんのおかげです。本当にありがとうございました。

もう研究室を出ないといけない
働きたくないでござる!!!

やっぱり出来事が10個も集まらない
頑張って集めてみたけど、9個が限界でした。

evalを使えばルンルン気分

12月 26th, 2011

【evalを使えばルンルン気分】

「Lispは楽しいと聞いたのですが、どのあたりが楽しいのでしょうか?」
こういった質問に対して返す言葉。白い目で見られることまちがいなし。

nconcでこんくらい速くなる

12月 26th, 2011

【nconcでこんくらい速くなる】

「このプログラム、もう少し速く動きませんかね」と、
appendを使ったプログラムを見せられたら、
(安全な)appendをnconcに書き換えて実行し、このように言いう。
相手が鋭い場合「最初のnは何処に消えた?」と聞かれることもあるが、
その場合は「副作用で破壊された」などといってごまかす。

クォートを使えばいーんよ

12月 26th, 2011

【クォートを使えばいーんよ】

「Lispはプログラムをデータとして扱えると聞いたんですが、どうやるんですか?」
このように聞かれたときには、こう答えよう。
ただし「それじゃあクォートを使っていこぉーっと」という反撃に注意。

メリークリスプマス!

12月 25th, 2011

【メリークリスプマス!】

クリスマスにこのセリフを言って、みんなを凍り付かせよう。

環境問題を考えずに関数を作っていくと、いつか後悔するよ

12月 24th, 2011

【環境問題を考えずに関数を作っていくと、いつか後悔するよ】

「高階関数を積極的に使って、なんでも関数で表現するべきですよね」という
過激派に向けて使う言葉。昔のLISPを知らないと通じない可能性がある。
また、処理系を作ってる人に対して使うこともできる。