K.Maebashi's BBS

ご自由に書き込んでください。雑談も可。
テスト書き込みの類はテスト用掲示板にどうぞ

[日付順表示] [日付順インデックス] [スレッド順インデックス]

新規投稿 | 開設者ホームページへ戻る | ヘルプ

[2128] いろいろ愚痴りたい((プログラミング言語を作る3章~5章 )
投稿者:mano
2018/04/30 19:02:25

ゴールデンウィークで読み終えられるかなと思っていたけど全然そうじゃなかった。 やっと、5章まで読み終わった。で、いろいろ愚痴りたい。(今回は投稿にパスワードをつけたので消す準備はバッチリです。) まずは、環境依存の問題 今週末は一人で0x0d問題にぶち当たり全然読み進められなかった。 test.crbを食わせても以下のメッセージしか出ない。 5:(0x0d)@ win_sjisのtest.crbだと、改行にCR(0x0d),LF(0x0a)が入れられていて、 今使っている処理系(Microsoft Windows Subsystem for Linux上のubuntu) では、0x0dを無視してくれず、改行コード\n(=0x0a)に到達する前に不正な文字で引っかかっている、がubuntuのターミナルは、SJISを解釈してくれず文字化けを起こす。結局が悪いのかがわからない。 今の時代趣味でやる分にはsjisもeucも地雷じゃないかなあ? で、読む気力がそがれたので、重箱の隅を突っ込みながら(またしても)表面をなぞる程度の読み込みになっちゃった。ちゃんと読めるのはいつのことになるんだか。。。 で、突っ込みはこんな感じ。 電卓の場合yyparse()で無限ループしているのに、crowbarではyyparse()以降の処理に進んでいることは誰も疑問に思わないのかな、 とか p.121 2個目のelse if文の中の処理、  left_val.u.double_value=left_val.u.int_value; eval_binary_double(...) の部分で、left_val.typeは変えずに(INTのまま)格納する共用体にはdouble値を入れている。 その後left_valはそのまま使わず、left_val.u.double_valueのみ使っているので問題にはならいけど、読んでて不安になる。なぜdouble(専用のというか普通)の型のローカル変数を使わないのかな? とか、 p.141の網掛けの以下の記述  a={1,2,3}; a={2,3,4}; のあとの図で、aから出ている矢印が{4,5,6}を指している。 {4,5,6}というのはどこから出てて来た?というか{2,3,4}はどこいった? とか、 p.145のビットフィールド。別にCのプロフェッショナルを目指す本ではないので、ビットフィールドなんて説明が必要な機能なんて使わずにしれっとCRB_Boolean使ったり、そのままズバリintを使えばいいじゃない。 とか、 p.153のダイナミックスコープの説明でnextから辿る場合、 仮に自身と呼び出し元に同じ変数名を定義し、自身内で変数を参照する場合、先に呼び出し元の変数が検知されてしまうので、ダイナミックスコープの動きと違うのでは? とか、 p.178 mbstate_をmemset()等でゼロクリアというmbstate_ってどこから出てきた? って感じです。あと、5章UNICODEについては、組み文字以外にデータ内に入っている(文字送り方向や字形の変更など) 制御コードをどう扱っているのかも書いてあればななあとも思いました。この辺って、例えば1文字のはずなのにデータは100byteとか作れそうで、セキュリティホールになりやすい感じがするので、なぜ問題にならないかを聞きたかったかも。
[この投稿を含むスレッドを表示] [この投稿を削除]
[2129] Re:いろいろ愚痴りたい((プログラミング言語を作る3章~5章 )
投稿者:(ぱ)こと管理人
2018/05/02 16:46:30

>win_sjisのtest.crbだと、改行にCR(0x0d),LF(0x0a)が入れられていて、 >今使っている処理系(Microsoft Windows Subsystem for Linux上のubuntu) >では、0x0dを無視してくれず、改行コード\n(=0x0a)に到達する前に不正な文字で >引っかかっている、 なるほど、crowbar.lでは「\n」だけを改行扱いにしていますから、 UNIX環境下では0x0dは不正な文字として扱われますね。 もともと、Windows(かつてはDOS)にてCでテキストファイルを扱う際、 改行を\r\nとして扱わなければならないのでは既存のUNIXベースの ソースが軒並み壊滅するので、Windows/DOS環境下では、fopen()とか fgetc()とかの標準入出力ライブラリのレベルで、\r\nを\nに変換するという 対策を取っています(バイナリファイルを扱いたいときにはfopen()に "r"の代わりに"rb"を渡す)。「Microsoft Windows Subsystem for Linux上のubuntu」 ではこの動きにならないのは、WindowsではなくLinuxであるためでしょう。 >今の時代趣味でやる分にはsjisもeucも地雷じゃないかなあ? まあそのあたりは、2009年の本ですので(その当時でもちと古かったのかも しれませんが)。 >電卓の場合yyparse()で無限ループしているのに、crowbarではyyparse()以降の >処理に進んでいることは誰も疑問に思わないのかな、 電卓では入力が終わりませんからね。 >p.121 2個目のelse if文の中の処理、 > left_val.u.double_value=left_val.u.int_value; > eval_binary_double(...) >の部分で、left_val.typeは変えずに(INTのまま)格納する共用体にはdouble値を入れている。 >その後left_valはそのまま使わず、left_val.u.double_valueのみ使っているので >問題にはならいけど、読んでて不安になる。なぜdouble(専用のというか普通)の >型のローカル変数を使わないのかな? ちょっと当時の意図は思い出せませんが、左辺をdoubleに型変換した 感じを出したかったのかもしれません。確かに今見ると、ちょっと意図の よくわからないコードになっているとは思います。 >p.141の網掛けの以下の記述 > a={1,2,3}; > a={2,3,4}; >のあとの図で、aから出ている矢印が{4,5,6}を指している。 >{4,5,6}というのはどこから出てて来た?というか{2,3,4}はどこいった? >とか、 p.146ですね。誤植のようです。正誤表に載せておきます。 ご指摘ありがとうございました。 >p.145のビットフィールド。別にCのプロフェッショナルを目指す本ではないので、 >ビットフィールドなんて説明が必要な機能なんて使わずにしれっとCRB_Boolean >使ったり、そのままズバリintを使えばいいじゃない。 これにはたぶん段階のようなものがあって、 (1)unsigned long flagsみたいは変数にフラグを押し込んで、  自力でビット演算 (2)ビットフィールド (3)しれっとなんでもCRB_Boolean 当時、実用に供されているCのコードだと、(1)が多かったと思います(ひょっとすると 今でも)。それに比べれば進歩(?)だと思っておいてください。 (本にも「まあ、富豪的プログラミングの感覚からすれば、1ビットのフラグでも、 CRB_Boolean型ひとつ割り当てるべきなのかもしれませんけど。」と書いていますが) >p.153のダイナミックスコープの説明でnextから辿る場合、 >仮に自身と呼び出し元に同じ変数名を定義し、自身内で変数を参照する場合、 >先に呼び出し元の変数が検知されてしまうので、ダイナミックスコープの動きと >違うのでは? 最新のLocalEnvironmentを起点にnextをたどって変数を検索すると、 先に検知されるのは呼び出し元ではなく自身の方なのでは……? 一応ver.0.2のeval.cのalloc_local_environmentを確認しましたが、 新LocalEnvironmentのnextに、その時点でのトップのLocalEnvironmentを 連結していますし。 635: ret->next = inter->top_environment; 636: inter->top_environment = ret; >p.178 >mbstate_をmemset()等でゼロクリアというmbstate_ってどこから出てきた? 文脈からすると「mbstate_t」の誤りのようです。正誤表に載せておきます。 >って感じです。あと、5章UNICODEについては、組み文字以外にデータ内に入っている >(文字送り方向や字形の変更など)制御コードをどう扱っているのかも書いてあれば >ななあとも思いました。この辺って、例えば1文字のはずなのにデータは >100byteとか作れそうで、セキュリティホールになりやすい感じがするので、 >なぜ問題にならないかを聞きたかったかも。 この本のプログラムでは、「mbrtowc()を信頼する」というスタンスですかね……
[この投稿を含むスレッドを表示] [この投稿を削除]
[2130] Re:いろいろ愚痴りたい((プログラミング言語を作る3章~5章 )
投稿者:mano
2018/05/03 16:13:46

回答ありがとうございます。(1か月ぐらいした後に消そうと思っていて、正直回答を期待していなかったので少し驚きました。) >>p.153のダイナミックスコープの説明でnextから辿る場合、 >>仮に自身と呼び出し元に同じ変数名を定義し、自身内で変数を参照する場合、 >>先に呼び出し元の変数が検知されてしまうので、ダイナミックスコープの動きと >>違うのでは? > >最新のLocalEnvironmentを起点にnextをたどって変数を検索すると、 >先に検知されるのは呼び出し元ではなく自身の方なのでは……? >一応ver.0.2のeval.cのalloc_local_environmentを確認しましたが、 >新LocalEnvironmentのnextに、その時点でのトップのLocalEnvironmentを >連結していますし。 > >635: ret->next = inter->top_environment; >636: inter->top_environment = ret; > > うーん、コード読んでないのがバレました。(だって人が書いた長いコードをインタビューなしで読むのはしんどいもの。。。)で、nextの音の響きから、左から右、上から下、低層から高層(深層)の方向と想定してました。 だから、「最新のLocalEnvironmentのみから検索しますが、nextをたどって、呼び出し経路すべてのLocalEnvironmentから検索するようにすると、」の記述を、 「「最新のLocalEnvironmentのみから検索しますが、【トップレベルでの(グローバル変数に格納された)LocalEnviromnent型の変数を参照の後】nextをたどって、呼び出し経路すべてのLocalEnvironmentから検索するようにすると、」 と補って読んでいました。 なので、nextの本来の使い道はガベージ判定で、ダイナミックスコープ判定の用途でも使えることを言っているのかな?と類推していました。 ま、この部分の私の理解は大体間違っていましたね。 とりあえず、私の理解不足を棚上げしておいて、別の意味に捉えかねないnextの名前が悪い、っと愚痴っときます。(えぇ暴論ですとも。)
[この投稿を含むスレッドを表示] [この投稿を削除]