ゴミ屋敷のクリーニングに取り掛かる

全189点のZTシステム構成図7.ZELを直系親族図で開いて閉じると,アプリ終了時に実行されるCallSetCouplingPtrの入口で,ゴミ箱に5302個,Nringに3318個,合計8620個のオブジェクトが入っている.Nringには現在アクティブなオブジェクト,ゴミ箱には廃棄されたオブジェクトが入る.Nringの内訳を見ると,最多はNODEREFLISTで1296,次が基本クラスのnoduleで1256,CARDLINK 189,SIMPLEEDGE 153,SIMPLENODE 119,REFLINK 119,MARGLINK 88,COMPLIST 41,longtable 11,SIMPLEGRAPH 9,NODELIST 9,EDGELIST 9,nlist 2のように続いている.CARDLINK 189とMARGLINK 88はファイルに含まれる人名と結婚の総数を示している.

NODEREFLIST(参照リスト)は「永続性オブジェクト」と定義され,「終末期」でも存続することになっているので1296というのは「参照を持つオブジェクト」の総数を示している.SIMPLEGRAPH(検定用枝グラフ)が9個残っていて,NODELIST 9,EDGELIST 9,COMPLIST 41,SIMPLEEDGE 153,SIMPLENODE 119はすべてその関係だ.SIMPLENODEとREFLINKの個数が一致しているのはなぜだろう?nlistはテンプレートクラスで裸のnlistという使い方はないはずなのだが,2個存在している… longtable 11というのは長整数配列ですべてカードのシステム通番を格納してそれぞれの用途別に使っているはずだ.無名のnoduleが1256個もあるというのは驚異だ.何に使っているのか?見当も付かない.ほぼゴミ屋敷と言っても過言ではない.

特に問題なのはNODEREFLISTの始末だ.新しいファイルがオープンされ,ほとんどのノードがゴミ箱に移動した後でも,削除禁止状態になっているNODEREFLISTだけはNringに留まることになる.これはゼロエミッションの観点からするとかなり問題がある.ゴミ箱の中のオブジェクトはリサイクル可能だが,Nringにあるものはすでに不用の状態でも再利用できない.⇒NODEREFLISTを一括解放するReleaseRefListという関数を用意した.この関数はCloseFamilyBaseの出口で実行するのがもっとも安全であると考えられる.⇒これでCallSetCouplingPtrの入口におけるNODEREFLISTの個数は1296→483まで減少した.

しかし,この位置でCARDLINKとMARGLINKが存続しているというのはかなり疑問だ.COUPLING::CloseFamilyBaseの出口では

DEBUG_NEVER (topology && (topology->PDB->getmaxrecn() || topology->MDB->getmaxrecn()))

でテーブルが空であることを確認している…CARDLINKやMARGLINKはこれらのテーブル(MDB, PDB)以外には居場所はないはずなのだが… ⇒いや,テーブルにはリンクがそっくり残っている.どういうことだろう?CloseFamilyBaseは引数のmodeがTRUEでなければEraseFamilyTreeを実行しないようになっている.それはそれでよいとして,中身が詰まっているのにmaxrecnがゼロというのはかなりまずい.どこでリセットしているのだろう?⇒そもそもCloseFamilyBaseはつねに引数TRUEで呼び出されている.どこかに欠陥がある.

CloseFamilyBaseはmode ONで呼び出されているが,この中から呼び出されるEraseFamilyTreeにはmodeが渡されていない.つまり,FALSEで呼び出している.EraseFamilyTreeがTRUEで呼び出されるのは終了処理のCallSetCouplingPtrで単独で呼び出されるケースの場合だけだ.EraseFamilyTreeではmodeがFALSEのときには,LINKTABLE:ClearTableを実行し,TRUEのときにはFAMILYTREE::CleanSlotを実行している.CleanSlotはNODULEクラスの共通関数で,デフォルトでは接続を含めたすべてのスロットを空にする動作になっている.

問題はLINKTABLE::ClearTableだ.この関数ではmaxrecnなどのパラメータのリセットしか行っていない.LINKTABLEのClearTableはBASETABLEのClearTableを上書きするもので,中からBASETABLE:ClearTableを呼び出している.この関数ではcleartableでパラメータをリセットし,CleanSlotをデフォルトモードで実行して全スロットをクリアしている.にも関わらず,リンクが残っているというのはなぜか?

CleanSlotは共通定義マクロで定義されている共通関数なのでトレースできない.マクロのコピーから別関数を仕立てて試してみよう.⇒なぜテーブルがクリアされないのか分かった.BASETABLE自身のスロットはlookupだけで,テーブル本体は基本クラスのARRAYが持っている.従って,ARRAYをCleanSlotしなければ意味がない.いや,実際BASETABLEのデストラクタでは以下の行でそれをやっている.

ARRAY<bnum>:CleanSlot(); 

lookupはlongtableなのでパーツとして温存しておいても差し支えはない.ARRAYの派生クラスにはこの他,REFLINKとTRASHCANがある.⇒対処した.これでNringに残ったオブジェクトは当初の3318→557まで減少した.検定グラフがこの時点でも残っているというのはおかしいので,どこかでパージしておこう.

現行ではSIMPLEGRAPHのインスタンスは9個あって,すべてTOPOLOGYの所有になっている.EraseFamilyTreeではmodeがONのときはTOPOLOGYを削除しているが,OFFのときには何もしていない.⇒すべてのグラフをパージする論理を追加したが,問題がある.アプリ起動時にはグラフを生成・初期化しているが,OpenFileBaseでは特に何もしていないため,系統並び替えに入ってからグラフ不在で停止してしまう.OpenFileBaseの中で多分TOPOLOGYを初期化しているところがあるはずなので,そこでグラフの存否を確認することにしてみよう.

OpenFamilyBaseでは特に何もしていない.その上位関数であるOpenFamilyTreeではInitializeFamilyTreeを実行している.TOPOLOGYはFAMILYTREEが管理しているので,この中で実行されるのが妥当だろう.ここで一つ疑問なのは,InitializeFamilyTreeを実行した後で,CloseFamilyBaseが実行されるという点だ.この点は前から疑問があったので実行順序を変えるなどのことを試しているが,変更すると逆に動作しなくなったりするため放置状態になっている.

やはりダメだ.系統並び替えに入って,TITLEBOX::SetDispParmでエラーが起きている.TITLEBOXは設定されている.(pdc->GetMapMode() == MM_TEXT)というエラーだ.このデバイスコンテキストはCOUPLINGがウィンドウのハンドルから取り出したものだ.座標計算をしているのだから,論理座標系でなくてはならないはずだが,いままでその辺りを気にしたことはない… 後ろの方でsetMappingをやっていたので,前方に移動した.⇒完璧に動作するようになった.

▲GetDCCは40箇所の出現がある おそらく必要な箇所にはsetMappingが入っているものと思われるが,今回のように「たまたま動いている」場所もあるのではないか?

Nringに残っているオブジェクトの個数はわずか43個まで減少した.グラフを外しただけでここまで劇的に減少するという理由はよくわからないが,ともかくこれで,システムはほぼ「コア」を残すだけの状態になったと言ってよい.あと,気になる点として以下が残るだけになった.

  1. 生のnoduleが7個ある.これは何か?
  2. 生のLISTが1個ある.これは何か?
  3. 生のnlistが2個ある.これは何か?
  4. NODEREFLISTが4個ある.これをゼロとすることは可能か?

(1)はおそらく,NODULEのstaticオブジェクトではないかと思う.確認する方法はあるだろうか?⇒すべてLISTELEMENTというラベルが付いている.「固有データ部を用いる直列リスト要素オブジェクト」でDATALISTで要素を追加するDATALIST::putで設定している.LIST:insertでも同様のことをやっている.NLIST::put,insertも同様だ.LISTELEMENTはリスト生成時に指定したデータサイズを持つ無名のnoduleでここにデータを書き込んでさまざまな用途に用いる.LISTELEMENTが他の用途に流用されることはないと考えられるから,本来ならリストを削除したときに同時にゴミ箱に入っていなくてはならないのだが,そうなっていないのはなぜだろう?リスト操作にまだ何かしら不備が残っているのだろうか?snumは14, 32, 34, 38, 40, 61, 62というかなり若い番号を持っている.

おかしい.nodl_floatを通っていない.⇒setNringでつかまえた.参照リストの要素オブジェクトだ.どうもこれは存続しているコアオブジェクトの保持する参照リストの要素であったように思われる.しかし,ReleaseRefListでは参照リストのデータカウントがゼロでない場合には削除しないようにしているのだが… 仮にリストが何かの理由で削除されたとすれば,同時に削除されているはずだし… 可能性として,フェーズが BEGININGSになっていれば,~NODULEで全スロットクリアの対象になる可能性がある… ⇒単純な理由だ.まだ存続しているNODEREFLISTが4つある.これらリストのリスト要素だ.

(2)生のLISTというのは確かにどこかで使っていたような気はするが,何に使っていたのかは覚えていない… 親ノードはTRIBELISTだ.splitlist(系列間シンメトリ婚スプリット検定用リストへの参照)というのがある.@20201102廃止というコメントが付いているが,見たところ依然として存続しているようだ.⇒TREIBLIST::splitlistであることは間違いない.このような特殊オブジェクトを生成したときには「名前」を設定しておいた方がよい.⇒nam1を「SPLITLIST」とした.

(3)も同じような事情だろう.これらには,SYMMETRYLIST,TOOYOUNGLISTの名前を付けておいた.(4)のNODEREFLISTの親はTREEVIEW, CARDTABLE, MARGTABLE, GENELISTだ.これらを削減するには,参照を廃止して関数化すればよいのだが,参照元がどこかを突き止めなくてはならない.⇒BreakNringを書き直して残ったNODEREFLISTをダンプしてみよう.最初の3つは2箇所から,最後の1つは1箇所から参照されている.

  1. PAGESETUP→TREEVIEW
  2. TRIBELIST→TREEVIEW
  3. TOPOLOGY→CARDTABLE
  4. NAMESORT→CARDTABLE
  5. TOPOLOGY→MARGTABLE
  6. NAMESORT→MARGTABLE
  7. TRIBELIST→GENELIST

バックアップを取っておこう.PAGESETUP→TREEVIEWの修正は難なく終わったが,次のTRIBELIST→TREEVIEWでエラーが発生した.

ZTシステム構成図7.ZELを基準ノード=202 NODULEで開いて,系統並び替え中GoDownStream→setstarttribe→Sansyoで(previous && previous->getpnode() == this && previous->getpnum() == edan) で停止 これは「接続用スロットには参照設定できない」という意味だ ⇒クリーンビルドしたらまたコンパイルエラーが出てきた.

同上サンプルで起動して系統並び替え中のClearTable→…~NANEBOX→…GetGeneBoxで停止 (gnum < 0)が発生している ⇒再実行したらエラーなしでファイルを開いた.

NODEREFLISTは1個減って3になった.最後のTRIBELIST→GENELISTを先に見ることにしよう.

▲同上サンプル→TribeRelocation→…GENELIST::InsertGeneBoxで停止した.原因は世代枠不在(!gbox).クリーンビルドして何箇所もコンパイルエラーが出た.⇒その後,再起動して解消した.

PDB,MDBの修正完了後実行して,OpenFamilyBase→ InitializeFamilyTreeでgetmaxrecnを実行しようとしてアクセス違反例外が発生した ⇒上記と同様コンパイルエラーがなくなるまでクリーンビルドを繰り替えして解消した.参照スロットPDBを廃止してPDB()のように関数化したところは285箇所,MDB→MDB()は108箇所.

▲修正がすべて完了した後に起動して上記と同じ→…~NANEBOX→…GetGeneBoxで停止するエラーが発生 ⇒バグと認定される.起動後に系統並び替えすると発生する.今回は#11 extraslot2dedeで起きたが,多分別のカードでも起きると思う.ClearTable中に起きている.ClearTable実行中に世代を問うということが果たして正当と言えるのかどうか?今日は寝て,明日また考えることにしよう.

コメントを残す

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

CAPTCHA