昨日やり残したところから始めるとしよう

昨日やり残したところから始めるとしよう.「toplistを関数化し,もし,リスト先頭要素が「脳死状態」と判定された場合には,次ノードを返す」という修正だ.⇒DATALIST::toplistをlisttopとリネームし,toplistをすべてtoplist()に一括変換した.⇒一つ問題が出てきた.LIST::swapではtoplist を直接書き換えている.これは親子接続関係の書き換えも含むかなりクリティカルな操作だが,listtopはDATALISTのprivateとして外部からのアクセスを禁止するようにしたい.⇒この関数自体をDATALISTに移管するのが適当ではないか?コンパイルは通ったが,リンクでPAIRLIST *toplist()が未解決の外部参照になった.関数の内部でローカル変数としてtoplistを使っていたところがある.

ZTシステム構成図7.ZELを#201 noduleで起動→終了してnodule::operator deleteで参照カウント残が出た.障害ノードはTRIBEBOX#7865,参照は2つ残っている.TRIBELIST#32の枝4と5だ.これはbrokenとstarttribeに相当する.これをクリアするのは,TRIBELIST::dataCountDownの役割だろう.⇒いや,そのロジックはすでに実装済みだ.DATALIST::findはリスト要素検索のとき,toplist()から検索している.DATALIST の操作ではtoplist()は使えないのではないだろうか?⇒いや,多分これだけだ.findで削除中ノードが検出できることと,toplistの関数化は裏表の関係がある.どちらも欠かせない.

これで少なくともリスト操作に関しては欠けるところのない状態になった.大きな修正ではないがバックアップしておこう.⇒動作はかなり安定してきているが,この際なので懸案を片付けておきたい.秩序だった解体を実現するために不可欠な要件はリストやチェーンを崩さずに解体を進めるという点にある.リストに関してはほぼそれを満たすところまで来ていると思われるが,チェーンに関してはほとんど未着手と言ってよい.ポイントはチェーンを管理する親ノードを子ノード側から突き止めることができるようになっていなくてはならないという点だ.

たとえば,同一世代人名枠チェーンの場合,NAMEBOXでは自ノードの世代から所属世代枠を決めなくてはならないが,世代というパラメータには有効期間というのがあるので,つねに確実に操作することを保証できない.これを避けるためのもっとも簡便な方法はチェーンをリング化することであると思われる.チェーンを操作する汎用関数のセットはすでに存在しているが,現行論理はそれなりに閉じているので,これをもう一度書き換えるのも得策ではない.要は末尾をつねに親オブジェクトにリンクすることになるのだから,それほど難しい修正ではない.

どこから着手すればよいか?Sansyo(GENEBOXsSAMEGENE)を操作している関数は2つある.GENELIST:AddSameChainとGENEBOX:ReleaseSameChainだ.また,GENEBOX::FindSameChainという検索関数もある.GENEBOXでは samegeneとbottom1を管理している.NAMEBOX *samegeneがこのチェーンを構成するためのスロットだ.もし,既存論理がbottom1を正しく管理できているのなら,修正箇所を見つけるのは簡単だ.Sansyo(GENEBOXsBOTTOM…を実行しているところを見つけて,bottom1からGENEBOXへの参照を設定するだけでよい.このような場所が8箇所ある.この修正は「同一世代人名枠チェーンをリングに転換@20201201」としておこう.修正箇所は以下の通り.

  1. GENEBOX::CleanSansyo
  2. GENELIST::AddSameChain
  3. GENEBOX::ReleaseSameChain

無論これだけでは足りない.少なくとも以下の修正が必要だ.

  1. 末尾ノードがリストから切断されたとき→sanemgeneをリセットする
  2. リングを走査するときの脱出口を設置する

上記サンプルを起動→終了してGENEBOX::CleanSansyoで末尾ノードが後続ノードを持っているというエラーになった.⇒これはエラーではない.親のGENEBOXだ.~NAMEBOXで同一世代人名枠チェーンの親世代枠を探索するのに,リングを使うように修正した.

同上サンプルを#24 UNDOCHAINでソートしようとして((primary->IsPrimGhost() || primary->IsLongTail() || primary->IsBundledString()) && (action && PHASE > CHAOTICSTATE && !primary->getghostbits(YOUNGERWIFE)))となったため停止した.PAIRLIST::Removeでノード対を削除しているところだ.系統並び替えのステージ【9】でCheckZeroPositionを使って「ZTYW婚の適正配置を実施」しているところだ.

この条件式の意味は,「ノード対の仮ノードは消去された仮ノードか長い尻尾ないし束ねられたLDR垂線のダミー仮ノードのいずれかで,かつ,検査中ではなくフェーズはINITIALIZEDより大で TYW参照を含む長い尻尾の中間に設置されるノード対の仮ノードでない場合」だが,IF文の条件が(PHASE > CLEARTABLE)となっているので,かいつまんで言えば,「TYW参照を含む長い尻尾の中間に設置されるノード対の仮ノード」は認められない,ないし,そのようなものを検出したときには停止するという意味になる.

YOUNGERWIFE(TYW参照を含む長い尻尾の中間に設置されるノード対の仮ノード)という属性が問題だ.この属性はNAMEBOX:CheckHorizontalDraftでセットされている.この関数は「長過ぎる尻尾のダミーノードの水平位置に差異が生じた場合,その部分をカバーするノード対を新規に追加する」ためのものだ.字句通り解釈すると,長い尻尾が曲がりくねることを認める(サポートする)と言っているように聞こえる.エラーを無視して描画できるので,チェックしてみよう.

image

画面上には存在しないので,どこかでリセットされたものと思われる.いや,間違えていた.条件式は「YOUNGERWIFEではないもの」だった.ということは,「かつ」の後ろはほとんどの場合成立するので,最初の「消去された仮ノードか長い尻尾ないしLDR束の仮ノード」であれば停止することになる.どうも意味不明なので「PAIRLIST:Removeの検査で停止しない@20201201」で一時停止しておくことにする.

大体問題なく動作するようになったようだ.チェーンはまだこの他にもいろいろ使われているが,これまであまりトラブルを起こしてこなかったように思われるのでしばらくこれで運用してみることにする.ここで一旦これまでの修正をフィックスしておくというのがよいのではないだろうか?その前に一つリリース版を起こしておくことにしよう.⇒Version 2.2.0.018 Release 2020-12-01とした.

上記サンプルを#202 NODULEでソートして終了しようとして,nodule::operator deleteで参照カウント=2というのが出た.⇒再現する.PAIRBOX #27851がEraseTreeViewの中で削除されるところだ.PAIRLIST#12519からの参照が2つ残っている.枝2と3はbottom2とcurnodだ.⇒PAIRLIST::findの冒頭でtop()が空を返している.LIST:topはtoplist()を返している.⇒PAIRLIST::findからDATALIST::findを呼び出すしかないだろう.toplistの関数化ということはtoplistの参照化を意味している.つまり,関数には参照ベースの関数と接続ベースの関数の違いがあることが認識されなくてはならない.

DATALISTは直列リストだが,PAIRLISTは端点共有リストを含む複合リストになっている.物理(接続)ベース)のfindと論理(参照)ベースのfindを切り分けるしかないのではないか?物理ベースのfindを使う場所は限定されているはずだ.前者を_find,後者をこれまで通りfindとしてみよう.あるいはremovingでクリティカル区間を区切った方がシンプルになるかもしれない…しかし,アノーマルな削除ではremovingを立てることはできない.⇒findにデフォルトFALSEの引数を設けて,TRUEのときだけ物理ベースで動作するというのはどうか?それがよいかもしれない.やってみよう.いや,それよりもtop関数に引数を渡す方が簡便だ.

DATALISTはtopという関数を持っていない.toplistとtopを使い分ければよいのではないか?topを論理ベース,toplist を物理ベースという使い分けが考えられる.現状では両者が混在しているが,まず,top()に一本化した後,必要な箇所ではtoplistを使うようにすればよい.これもややクリティカルな修正なので一度バックアップを取っておこう.

PAIRLIST::findを元の論理に戻しただけで解決した.先頭要素はtop()で取り出している.ただし,終了時参照カウントが残る事象が再発している.⇒DATALIST::toplistで物理先頭リスト要素を返すようにして,PAIRLIST::findではtoplistでリスト先頭を取り出すようにした.DATALIST::findは物理ベースで動作しているので,これで一応すべて筋が通ったことになる.何か問題が発生したらそのとき対応することにしよう.後は,現状でフィックスするだけではないだろうか?⇒まだリリース版を起こしていない… ⇒リリース版のビルドでエラーが出ている.

cl : コマンド ライン warning D9025: ‘/Zi’ より ‘/ZI’ が優先されます。
cl : コマンド ライン error D8016: コマンド ライン オプション ‘/GL’ と ‘/ZI’ は同時に指定できません

/ZI はエディットコンティニュをサポートする形式で PDB ファイルを生成する./GLはプログラム全体の最適化を有効にする.⇒どうも/ZIをリリース版の方で設定していたようだ.道理で,なんだか効きが悪いと思っていたのだが…

▲debugビルドで以下の警告が出る.「warning LNK4075: /EDITANDCONTINUE は /SAFESEH の指定によって無視されます。」以下のURLにvcxprojファイルを書き換えて対処する方法が書かれていたので試してみる.

https://qiita.com/gocha/items/d690f1240813aef8b303

かなりまずいことになった.ZelkovaDLL3プロジェクトが(利用不可)になり,プロジェクトファイルを元に戻しても復元できないようになってしまった.⇒バックアップをベースに修正ソースとヘッダだけ差し替えた.⇒これをビルドして以下のようなエラーになった.

1>   ライブラリ D:\ZELKOVA\\Release\ZelkovaDLL3.lib とオブジェクト D:\ZELKOVA\\Release\ZelkovaDLL3.exp を作成中
1>   コード生成しています。
1>d:\zelkova\zelkovadll\src\bugreportdialog.cpp : fatal error C1001: コンパイラで内部エラーが発生しました。(コンパイラ ファイル ‘d:\agent\_work\18\s\src\vctools\compiler\utc\src\p2\main.c’、行 187)
1> この問題を回避するには、上記の場所付近のプログラムを単純化するか変更してください。詳細については、Visual C++ ヘルプ メニューのサポート情報コマンドを選択してください。またはサポート情報 ヘルプ ファイルを参照してください。
1>  link!InvokeCompilerPass()+0x2f79a
1>  link!InvokeCompilerPass()+0x2e9f8
1>  link!CloseTypeServerPDB()+0xd5266
1>
1>d:\zelkova\zelkovadll\src\bugreportdialog.cpp : fatal error C1001: コンパイラで内部エラーが発生しました。(コンパイラ ファイル ‘d:\agent\_work\18\s\src\vctools\compiler\utc\src\p2\main.c’、行 187)
1> この問題を回避するには、上記の場所付近のプログラムを単純化するか変更してください。詳細については、Visual C++ ヘルプ メニューのサポート情報コマンドを選択してください。またはサポート情報 ヘルプ ファイルを参照してください。
1>  link!InvokeCompilerPass()+0x2f79a
1>  link!InvokeCompilerPass()+0x2e9f8
1>  link!CloseTypeServerPDB()+0xd5266
1>
1>LINK : fatal error LNK1000: Internal error during IMAGE::BuildImage
1>
1>  Version 14.16.27043.0
1>
1>  ExceptionCode            = C0000005
1>  ExceptionFlags           = 00000000
1>  ExceptionAddress         = 02ED3E6D (02A40000) “C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\bin\HostX86\x86\c2.dll”
1>  NumberParameters         = 00000002
1>  ExceptionInformation[ 0] = 00000000
1>  ExceptionInformation[ 1] = 00000024
1>
1>CONTEXT:
1>  Eax    = 00000000  Esp    = 00E9E810
1>  Ebx    = 0000000C  Ebp    = 00E9E820
1>  Ecx    = 0000A246  Esi    = 25541F0A
1>  Edx    = 00000000  Edi    = 2263102C
1>  Eip    = 02ED3E6D  EFlags = 00010212
1>  SegCs  = 00000023  SegDs  = 0000002B
1>  SegSs  = 0000002B  SegEs  = 0000002B
1>  SegFs  = 00000053  SegGs  = 0000002B
1>  Dr0    = 00000000  Dr3    = 00000000
1>  Dr1    = 00000000  Dr6    = 00000000
1>  Dr2    = 00000000  Dr7    = 00000000
1>プロジェクト “ZelkovaDLL.vcxproj” のビルドが終了しました — 失敗。

クリーンビルドして解消した.

上記「warning LNK4075: /EDITANDCONTINUE は /SAFESEH の指定によって無視されます。」は以下で解決した.「ソリューションのプロパティから、「リンカー」→「詳細設定」→「安全な例外ハンドラーを含むイメージ」を「いいえ(/SAFESEH:NO)」に変更します。」http://replication.hatenablog.com/entry/2016/04/13/233924

▲リリース版をインストールして上記サンプルの全体図テストを実施して,#195で停止した.#196, #197でも起きる.BUG20-12-02 01-34-26.ZELで再現できる.⇒メインループを3回回っている.メインループを直列処理に変えられるのではないかと思っていたのだが,反例が出てしまった.この件はしばらく保留とする.

今回の改修は2020/11/18頃から始まっている.仕掛りのOPTIONSが9件,仮修正が37件,暫定修正が2件,#ifdefが107箇所,#ifndefが102箇所ある.最初に仮修正と暫定修正をフィックスしてしまおう.

コメントを残す

メールアドレスが公開されることはありません。

CAPTCHA