NODULE::operator []で例外が発生した 枝番はSEIZEGROUND

従来論理ではCOUPLING:EraseFamilyTreeでFAMILYTREEの下にあるすべてのスロットをパージしていた.この中にはTOPOLOGYやUNDOSYSTEMも含まれる.EraseFamilyTreeはデータファイルをクローズするたびに実行されているが,実際にはNOPで抜ける動作になっていて終了時に一度だけ実行されるようになっていた.これは関数の趣旨からしておかしいので,EraseFamilyTreeではシステムに1個しか存在しないようなオブジェクトはパージしないように仕様変更し,同時に冒頭で(PHASE <= INITIALSTATE)によって抜ける論理を廃止した.

TITLEBOXはシステムに1個しかないオブジェクトだが,描画オブジェクトはEraseFamilyTreeの中ですべてパージされるようになっているので,その規定に従って削除されるように変更した.この修正は「タイトル枠無しで動作する@20201119」でオプトアウトできる.

TITLEBOXが空でも動作するようになったが,削除されたTITLEBOXをどこかで補充しなくてはならない.どこでそれをやればよいのだろう?ファイルを開いたときどこかでTITLELINKを初期化ないし設定している場所があるはずだから,そこで行えばよいのではないか?TITLELINKクラスのメンバー関数には大したものが入っていない.

いや,その前にFAMILYTREE::InitializeFamilyTreeで(topology->PDB->getmaxrecn() || topology->MDB->getmaxrecn())が起きているという件を先に片付けておこう.これがそもそもの発端だ.EraseFamilyTreeは毎回実行されるようになったが,PDB,MDBが始末されていない.これはTOPOLOGYが管理しているものだ.その直前でTOPOLOGY::initializeが実行されているが,この関数は働いていない.

nodule::operator newのcheck文で(*moto)[edan]をチェックしようとしたところ,NODULE::operator []で例外が発生した.枝番はSEIZEGROUND.⇒SEIZEGROUNDはサポート範囲外.(*goo)[SEIZEGROUND]ではnullを返すようにした.

新規ファイルで起動→サンプルを開いて,COUPLING:CloseFamilyBase→…TREEVIEW::EraseTreeView…→TRIBEBOXのデストラクタで非参照カウントの残留が発生 TRIBELISTのスロット2からの参照が解決していない.bottom2からの参照だ.TRIBEBOXのデストラクタで始末するか,ないしTRIBELISTを先にキャンセルするか,あるいはその両方をやる必要がある.TRIBEBOX::DisposeではTRIBELIST::CleanSansyoを実行している.⇒LIST::CleanSansyoでbottom2をクリーンアップしていない.⇒対処した.

PDB,MDBをクリアする件に関してはEraseFamilyTreeとTOPOLOGY::initializeの両方に責任がある.しかし,TOPOLOGYはPDBとMDBの管理者ではあっても,所有者ではない.所有者であるLINKTABLEには何かチャンスがあるのだろうか?どこかにPDB,MDBを初期化する処理があってしかるべきなのだが… LINKTABLEにはdeleteCardData,DeleteMarriage,DeleteCardなどの個別操作を行う関数はあるが,テーブル全体をクリアするという操作はない.BASETABLEにはcleartableという関数はあるが,これは単純にカウンタをリセットしているだけだ.

CARDTABLEとMARGTABLEはBASETABLEから単純に派生しているので,BASETABLEにClearTableを作るのが早いと思う.CleanSlotで掃除してから,cleartableを実行すればよい.その上で,LINKTABLEでPDBとMDBをClearTable.これをEraseFamilyTreeから呼び出せば片が付く.⇒単純化し過ぎている.ARRAYスロット配列はそれでもよいが,BASETABLEは追加スロットとしてlongtable *lookupというのを持っている.これはカウントをリセットすればそのまま再利用できるが,オブジェクトを削除してしまうとまた,トラブルの元になる.⇒lookupが空になっているときにBASETABLEがどう振る舞うかを見ておこう.

lookupはBASETABLEのコンストラクタで生成されているだけなので,これが空になることは想定されていないと思う.LINKTABLEはMakingLookUpで初めてloopupテーブルを操作する.ここで停止するか,ないし新たに生成するべきだろう.⇒MakingLookUpではlookupテーブルをゼロクリアしてから使っているので,ClearTableでは放置でもよい.この暫定修正でPDBとMDBのクリアはできるようにあったが,(PDB->getmaxrecn() || MDB->getmaxrecn())で停止するという状況は変わらない.これはgetmaxrecnの仕様に問題がある.現行では

long getmaxrecn(void) { return min(maxrefnum, tablesize); }

という仕様になっているが,かなり疑問だ.BASETABLEはmaxrecnというメンバ変数を持っているのだから,素直にこれを返せばよいのではないかと思うのだが… ⇒同じ轍を踏まないように注意した方がよい.「その場の思いつき命取り」が怖い.明らかにこのロジックではレコード番号と参照番号という2つの番号を扱っている.どちらもテーブルのインデックスだが,おそらくレコード番号は連番で参照番号というのは飛び番になっているのではないかと思う.通常,getmaxrecnとmaxrecnの値は一致していると考えているが,何かの理由でそうなっていないのではないか?そもそも,lookupテーブルというのはどんな必要があって使われることになったのか?どういう使われ方をしているのか?⇒これは一覧表出力に関係している.

いずれにしても,上記getmaxrecnの定義は正しいと考えるしかない.従って,必要なことはcleartableでmaxrefnumをリセットすることだ.⇒これで一応動作するようになったが,lookupを残すように修正しておこう.BASETABLE::ClearTableで一律CleanSlotではなく,

ARRAY<bnum>::CleanSlot

のようにスロット配列だけのクリアに変更する.これで大体収まった.BASETABLE::lookupをMakingLookUpで復活させたように,TITLEBOXにも再生処理を作ってみよう.⇒TILELINK::gettitleboxは描画フェーズでTREEVIEW::Refreshから呼び出される他は,COUPLING::SetTitleBoxからの呼び出ししかない.従って,ここで再生するというのが最適と思われる.TITLEBOXを必要としているのは,TREEVIEWなので,TREEVIEW::gettitleboxで生成というのでよいのではないだろうか?⇒いや,TITLEBOXはTITLELINKのコンストラクタで生成されているので,やはり,TITLELINKの位置で生成するのがよいと思う.事前にTITLELINKが呼び出されるようなタイミングがあればよいのだが,どうも見当たらない,ということになればTILELINK:gettitleboxで生成するしかないだろう.

TREEVIEW::InitTreeViewというのがある.これは毎回呼び出されているのではないか?OpenFamilyTreeではInitCouplingとInitializeFamilyTreeを実行している.InitTreeViewはInitCouplingの中で実行される.TREEVIEWはCOUPLINGの所有物だ.⇒いや,おかしい.いつ入れたのだろう.TREEVIEW::InitTreeViewの中にはすでにその処理が組み込まれている.だとしたら,「タイトル枠無しで動作する@20201119」というオプションは元々不要だったということになるのだが… しかし,何らかの必要があっての修正だったはずだ… 例外をスローして初めて発現する障害だった可能性もある.

FORMALVERSIONのテストなのでまず,その設定に戻してみよう.⇒何も障害が発生していないのに,新規ファイルを開いてTITLEBOXが空になっている.これはかなりおかしい.TREEVIEW::InitTreeViewで生成されたTITLEBOXはどこに消えてしまっているのだろう?⇒タイトル枠設定で「タイトル枠を表示」をONにできない.それ以外のパラメータもすべて変更できない状態になっている.

▲★ASSERT_NEVER★ PHASE=22 funcname=nodule::Connect scount=447534 line=591, filename=nodule.cpp MakePairListを実行中,RepairPairBoxでノード対のチャンネル移動を実施してtakeout→ nodl_float→ Connectで(moto == nodl)が発生している motoとnodlはともに空

「増設スロット(EXTRA_ANCHOR)の子ノード」を親ノードに接続し,ゼロスロットノードをそのノードのゼロスロット末尾に移動しようとしている.ノード対リストではノード対を管理するために増設スロットを使っている.(EXTRA_ANCHOR)は①端点共有ノード対接続チェーンと②SymmetricActionでブロック移動実行時に使われるリストを一時的に接続するために使われている.どちらも参照ではなく接続チェーンで,①の場合はPAIRBOX,②の場合はnlist<Bobject>が接続される.

nodule::nodl_floatの論理は明らかに誤っている.というか混乱している.混乱しているのは「増設スロットの仕様」だ.増設スロットは一時的にある特定クラスのオブジェクトがそのグループ内で使うものだから,「どう使われてもよい」というようなところがあったのではないだろうか?どちらも「接続」だが,接続のトポロジーは異なる.

ノード対の場合は増設スロットを使ったチェーンになっているが,SymmetricActionの場合は増設スロットに接続されるのはnlistでその下にゼロスロットを使ったリストがぶら下がるという構成になっている.従って,nodl_floatではこれらを一律に扱うことができないばかりではなく,ノード対の場合には接続に使うスロットをゼロスロットと誤認している.自ノードのXスロットに接続するノードは前方ノードのXスロットに接続し,自ノードのZスロットに接続するノードは前方ノードのZリスト末尾に接続するというのが原則だ.

nodl_floatは全面的に書き改めるしかない.⇒修正完了したが,スタックオーバフローが起きている.完全参照リスト管理の操作を誤解していたかもしれない.いや,いまの修正は参照リスト管理とは関わりがないはずなのだが… どうもどこか完全に壊してしまったようだ…

コメントを残す

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

CAPTCHA