ZTシステム構成図の構築が予想外に手間取っている

ZTシステム構成図の構築が予想外に手間取っているが,まるきり無駄なことをしているというものでもない.相当数のバグが出ているが,これらの大部分(99%くらい)は意図的に停止しているもので無害な動作と言ってよい.これらのSTOP文がなぜ各所に設置されているかというと,そのほとんどは過去の障害履歴と何らかの関係があるものと考えられる.これらはある種の免疫系を構築し,類似サンプルを見つけると停止するようになっているが,目的は希少な障害サンプルの収集にあり,防禦対策の効果を測定する「新薬開発時の治験」に相当する.

ゼルコバの木のテストでは自動生成されたサンプルを含め膨大な数のテスト用サンプルを使っているが,このところほとんど発現しなかったものばかりがぞろぞろ出てきているということは,このサンプルが相当程度難易度が高くZTシステムの堅牢性を検証する上での極めて効果的な検体になっていることを意味する.これまでに発生した致命的な障害は昨日のSUWくらいしかないが,これも当日の修正の結果に依るものであることは明らかなので,逆にゼルコバの木の健全性は相当なレベルで保証されたとも言える.このバグはそれほど(重要ではあるが)深刻なものではないのでそこそこの時間内にシューティングできるだろう.

直接の原因が結婚枠間ギャプをゼロからある数値に変えたことにあることは確かだが,どのような機序で衝突が発生しているのかは解明されなくてはならない.衝突が発生している時期にSUWで強制描画すると下図のような状態になっている.

image

この時点ではLDRは1本のLDR束にまとめられpagesetupの親子連結線とtreeviewの親子連結線は同じパイプを通っている.エラーを無視して強制描画した昨日の図ではLDRを2本個別に取ることによって解決しているが,これは本来の作図法ではない.衝突の当事者ノードはpagesetupの入っている箱#741とその隣にある垂線格納用の結婚枠#745だ.LDR束の移動は先頭LDRを移動することによって実施されるので移動対象はpagesetup(1)になるが,それに繋がるpagesetup(0)の入った結婚枠がpagesetup(1)を親参照しているため,連動してしまい.結局衝突は回避できないという状態が反復している.

LDR束の移動を実施しているMoveLongTailは「LDR束代表ノードを主語として呼び出され,LDR束全体を指定量moveだけ移動する」としているのだから,明らかにこのような事態が発生することを予定していない.ただし,この関数の中ではLDRの下流に連結されたTYW結婚枠だけはこの移動から除外している.類似した動作を行う関数としてMoveBundledLDRとMoveInvisibleBoxがある.

前者は「LDR束のLDRがすべてフローティングLDR(直下にTYW枠を持つLDR)の場合にはこの束を結婚枠内で隣接ノードと接触するまで前方ないし後方に移動する」としている.MoveLongTailの場合は除外対象となるのは直下のTYW婚1個だが,MoveBundledLDRでは下流のすべてのTYW婚を除外して移動を実行する.後者のMoveInvisibleBoxは不可視結婚枠を単体で移動するための関数で下流の結婚枠を一旦親参照パスから切断した後,移動を実行する.この他MoveNeutralという関数は相対矩形領域を直接操作することで移動を実施する.ただし,下流にある不可視の結婚枠とLDRではない不可視の人名枠は一緒に移動する.

MoveLongTailの動作を拡張して,下流にあるすべての可視の結婚枠を除外するようにすればよいのではないだろうか?いや,少し違う.MoveLongTailはoriginateを使わないで相対矩形領域を用いた相対移動を行っている.これなら影響は出ないはずだ.それも違う. LDR代表ノードは相対移動しているが,dummyboxの原点移動を行っている.もしこの結婚枠がダミー枠を親参照しているのならダミー枠の親参照リストから除外すればよいのではないか?あるいはLDRが入っている結婚枠を参照しているのかもしれない.

上の図を見るとpagesetupの結婚枠はTYW枠になっているように見える.だとすればMoveLongTailで処理できてもよいのではないか?・・確かに,margboxCollisionの後は衝突は解消している.ということはどこかでまた蒸し返しているということになる.つまり,MoveLongTailは問題なく動作していると言ってよさそうだ.

image

どこでそれを壊しているのだろう?この処理はMakePairListClean →BuildCompleteTreeの中にある.この中で解決されていることは昨日の段階で分かっている.確かに壊しているのは昨日見た通りCheckMargBoxChangedだ.[結婚枠]:#233と#89で「不可視枠を移動」が起きている.2つともpagesetupの空枠だ.前者は「ZTYW本人を参照する仮ノードが存在する元の親枠」+「親ノードに結合する(連結代表)子ども枠」で後者は普通の結婚枠だ.衝突は#741と#745で起きている.この不良はすでにCheckMargBoxChangedに入る前に起きる.つまり,結婚枠とその中の人名枠にずれが出ている.

image

結婚枠は人名枠の位置とサイズによって事後的に計算されているはずだから,悪いのはこの人名枠の位置ということになる.どこかでpagesetupとtreeviewを動かしている.⇒TRIBELIST:CheckInnerSplitだ.下位関数のTRIBEBOX::CheckInnerSplitでは系列枠のsplitlist(スプリット検定用リスト)を使って系列内に不正規に生じたスプリットを人名ノード間の区間を計算して計測している.

しかし,このsplitlistはかなり危ない使い方をしているような気がする.なぜこんなことをしているのか理解できない.splitlist のクラスはLISTであり,LISTはDATALISTの派生クラスだ.DATALISTはnoduleオブジェクトを数珠つなぎにした単純な線形リストで,そこまではよいが,noduleの固有データ部に無名の(型を持たない)ポインタを使ってCPointの読み書きをやろうとしている.これはどう考えてもかなり悪質だ.リンクされているオブジェクトがnoduleの派生クラスなら固有データ部は(通常)実在するが…

DATALISTのコンストラクタは引数を持つものもあり,そこでdatasizeを指定することができる.リスト要素を生成するときはそのようなdatasizeを持ったリスト要素を生成しているのだろう.しかし,どこでそれをやっているのだろう?小文字のsplitlistは小さくて探し難いのでSplitListにリネームしておこう.SplitListの出現箇所が少な過ぎる.⇒TRIBEBOX::TRIBEBOXに以下があった.

new (this, TRIBEsSLIST) LIST(sizeof(CPoint))

確かにこれでデータサイズがsizeof(CPoint)のリストが作れるだろう.SPLITLISTというクラスを作っておけばよいものをかなりひどい手抜きだ.LISTはデータポインタとしてvoid*を返すような作りになっているので,元々そういう設計だったのかもしれないが…

原因は単純だ.区間検査は結婚枠矩形領域を使って計算されているが,結婚枠間ギャップが加味されていない.marghgapはMARGBOX::heapBranchでは参照されているが,スプリット検定ではまるきり無視されている.TRIBEBOX::CheckGeneSplitのロジックを見ると結婚枠ではなく人名枠の区間を見ている.「ダミー枠を対象に加える@20170418」というコメントが入っているが,人名ノードしか取り出していないのでまるきり動作していない.ただし,ダミー枠の中には人名枠が入っているのでとりあえずこれでも動いている…

人名枠でなく結婚枠で問題ないと思われるのだが,何か不都合があるのだろうか?そもそも,スプリットを検出したときどういう方式で補修しているのだろう?⇒TRIBEBOX::SolveGeneSplitというところで処理されている.スプリットが検出された区間より右にあるものを(論理的には左)にあるすべてのオブジェクトをMoveNeutralで移動しているだけだ.これでなぜ人名枠と結婚枠にずれが生じるのかという理由もわかる.ここは結婚枠を対象に書き換えた方がよいと思う.

結婚枠を対象とするように書き換えただけでギャップを加算していないのに動作するようになった.結婚枠の相対矩形には元々ギャップが加味されている.⇒それではheapBranchの計算は間違っているのだろうか?いや,この計算は人名枠をヒープして結婚枠矩形を計算するものだから,これでよい.結婚枠を基準にすると先祖ノードが落ちこぼれる可能性がある.どうしたらいいだろう.

TRIBEBOX::stackTribeGeneでは系列世代枠リストを用いて集積している.この論理を踏襲するのがもっとも確実なのだが…この関数ではIsNameBoxVisibleとValidMargBoxを使ってそれぞれ人名枠と結婚枠の有効性を判定している.結婚枠をスキャンするにはringを使うのが一番効率がいい.そのために作られているのだから…

◎InvestigateHSplits,CheckInnerSplitなどは公式版では停止する.⇒SOKUDOSAIYUSENというフラグがある.

ズームの動作がおかしい.+をクリックして拡大する代わりに上に動いたり…画面に合わせてズームなども不調.⇒ShowUnderWearで強制描画しているためではないか?いや,違う.画面が更新されていない.部分図でだけ起きているように思われる.全体図・親族図では起きない.これまでは問題なく動いていたはずなのだが…と言っても少し前から不調には気付いていたが…最初からではないと思う.

TRIBEBOX::SolveGeneSplitもstackTribeGeneに合わせて書き換えることにする.⇒SolveGeneSplitの動作をチェックするにはスプリットを発生させなくてはならない.⇒やってみた.問題なさそうだ.これで系列内スプリット問題は全面解決した.

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA