====== 既知のバグ ====== 私が把握しているバグとその一応の対処 もっと前のリビジョンからのバグかもしれないし、そうでないバグかもしれない。 ===== check_implicit_lookupを呼び出してもチェックされない ===== ** r457で修正済み ** * なお、**xtal::debug::enable_debug_compile**を呼び出しておかないと、デバッグ情報が積まれずに有効に動作しないので注意。 定義されていない変数の参照をチェックするcheck_implicit_lookupだが、いつからか、呼び出してもチェックされなくなってしまっている。 次のように変えるとチェックが有効になる。 // xtal_code.cpp // 10行目付近 void filelocal_check_implicit_lookup(const AnyPtr& a){ if(const CodePtr& code = ptr_cast(a)){ code->check_implicit_lookup(); } } このようにすることで、次のような、定義されていない変数の参照が行われていないかどうかのチェックが行える。定義されていない変数の参照が行われていた場合、ランタイムエラーを発生させる。なお、定義されていない変数への代入はそもそもコンパイルエラーになる。 foo : 0; // filelocalへの変更が済んだら呼び出す check_implicit_lookup(); fun func(){ foo.p; bar.p; bar.p; hoge.p; } func(); 同名の未定義変数参照につき1回しか報告してくれないようである。上の例で言うと、barとhogeの暗黙参照が報告されるが、barは片方の行数しか報告されない。 動的にfilelocalに追加する場合(他のファイルやC++などから追加する場合を指す)には使うことはできないが、それ以外の場合には有用であろう。typo対策を想定した、というのが公式の見解である。たぶん。 ===== uninitialize時にファイバーが残っていると落ちる ===== ** r458で追加修正 ** \\ ** r456で修正済み ** r438+VCで再現 内部でInt.timesを使っていて、かつそのブロック構文を1回でも抜けたファイバーが残っているとuninitializeで落ちるっぽい。 // 落ちる fib : fiber(){ for (;;){ 1.times{yield;} } } fib(); fib(); // 落ちない fib : fiber(){ for (;;){ 2.times{yield;} } } fib(); fib(); // 落ちない fib : fiber(){ for (;;){ 1.times{yield;} } } fib(); fib(); fib.halt; // 落ちない fib : fiber(){ for (;;){ 1..1{yield;} } } fib(); fib(); // 落ちない fib : fiber(){ for (;;){ 1.times{yield;} } } fib(); fib(); fib = null; ===== VC++2010でコンパイルできない ===== ** r436で修正済み ** VC2008とは関数のルックアップの順番が変わっているのが原因っぽい(コンパイルできたという話もあり?)。 エラーの場所は、xtal_base.hのVirtualmembersOverwriteCheckerで静的にオーバーライトをチェックしている部分と、xtal_utility.hのConvertible, IsInherited。 次のように変えるとコンパイルできる。 // xtal_base.h // 71行付近から template struct VirtualMembersOverwriteChecker{ typedef char (&yes)[2]; typedef char (&no)[1]; // 他のは省略 // 頭にcheck_ってつけただけ static no check_visit_members(void (RefCountingBase::*)(Visitor&)); template static yes check_visit_members(void (U::*)(Visitor&)); enum{ // 他のは省略 // こいつもcheck_ってつける visit_members_overwrite = sizeof(check_visit_members(&T::on_visit_members))!=sizeof(no), }; こっち(xtal_utility.h)の方は、もしかしたらxtalprojのtestプロジェクトでない限りいじらなくてもすむかも。未確認。 // xtal_utility.h // 245行付近から template struct Convertible{ typedef char (&yes)[2]; typedef char (&no)[1]; static yes check_convertible(U); static no check_convertible(...); static T makeT(); enum{ value = sizeof(check_convertible(makeT()))==sizeof(yes) }; }; template struct IsInherited{ typedef char (&yes)[2]; typedef char (&no)[1]; static yes check_is_inherited(const U*); static no check_is_inherited(...); static T* makeT(); enum{ // 完全型チェック CHECK = sizeof(T) + sizeof(U), value = sizeof(check_is_inherited(makeT()))==sizeof(yes) }; }; [[http://twitter.com/heppoko/status/12643769394]] > エラーが出た visit_members_overwrite = sizeof(visit_members(&T::on_visit_members))!=sizeof(no) を 1 にするとVS2010でビルドできる。 #xtal_lang という話もある。確かにほんのちょっとオーバーヘッドが大きくなるかもだけどこれでも動く。 まあこの項の通りに変えておけば何も問題ないはず。 ===== ファイルローカルに4つ以上定義するとエラー ===== ** r438で修正済み ** 以下のようなコードでXtalが落ちる。 あくまでファイルローカル変数であり、関数内のローカル変数などでは大丈夫(たぶん)。 a : 0; b : 1; c : 2; d : 3; 原因は、xtal_vmachine.cppの1360行付近、XTAL_VM_CASE(InstSetFileLocalVariable)の内部でxarrayのサイズチェックをせずにset_atしてること。 とりあえずの対処としては、xtal_frame.hのclass Frameを直すと良い。 // xtal_frame.h // 78行付近 void set_member_direct(int_t i, const AnyPtr& value){ // これを追加 if (static_cast(members_.size())<=i){ members_.resize(i+1); } members_.set_at(i, value); } ===== ポインタをSmartPtrに暗黙変換すると落ちる ===== 報告済み **解決(勘違いでした、というやつですね)** XTAL_PREBINDを忘れるとこうなる、っぽい なので、コンストラクタや継承構造を記述しなくてもPREBINDだけは書く必要があるようだ。 ===== Class::overwrite がおかしい ===== ** r437で修正済み ** ver : r432以降 Class::overwriteを呼び出すと、メモリアクセス例外で落ちる。 以下のようなコードをリロードすると、アクセス例外が出たりする。uninitializeで落ちたり、overwriteで落ちたりする。 class Foo{ reloaded(){ "reloaded".p; } } if (global::?Foo){ global::Foo.overwrite(Foo); } else { global::Foo : Foo; } なお、r432-そのままでは、次のようなコードは1回リロードすると2回目以降はoverwriteが呼ばれない。 class global::Foo{ reloaded(){ "reloaded".p; } } 一応、xtal_class.cppの次の箇所を変更することで毎回overwriteが呼ばれるようにはなるが、僕の環境では割と高確率でメモリアクセス例外吐いた。 // xtal_class.cpp // 479行目あたり(r435) Class::overwrite_member // ... if(!dest->is_native() && !src->is_native()){ dest->overwrite(src); // FIX invalidate_cache_member(); return; } 正確な発生条件がわからず、わかりにくいメモリ破壊をしている気がするが、それも呼び出し方が悪いだけかもしれず…… ===== ライブラリ関連のミス ===== ==== Xtalで実装されている部分 ==== * fun xpeg::select で、return Eelement(...) になっている。 * 正しくは return Element(...) === Iterator::scanが動作しない === "foobar".scan(xpeg::pred(|x| x=="o")){it.p;} はうまく動くのに対し、 "foobar".each.scan(xpeg::pred(|x| x=="o")){it.p;} ではうまく動かない。 === ArrayIter::scanが動作しない === 実は上と同じ原因ではないか、とか思うけど未確認。 === Executor::matchにeosを食わせると確実にtrueを返す === eosをちゃんとeatしていないようだ。 ==== バインド関連 ====