メインループは当初(と言ってもかなり後になってからのことだが)タイムアウトでブレークするようになっていた.描画要素のレイアウト計算が無限ループに陥ってないし発散して停止しなくなる場合に備えての措置だ.その後はデバッグモードではループ回数オーバーでブレークするというオプションが導入されたが,リリース版では以前としてタイムオーバーを監視している.しかし,実際の動作ではつねにループ回数2回で脱出しているように思われる.これはすでにループ初回のラウンドで処理が完結していることを意味すると考えてよい.
言い換えれば,ここでは単純に処理を直列に実行するだけでよい状態になっていると言えるのではないか?ループを一回空回しするための時間コストがどの程度のものか分からないが,余分な処理はできる限り排除した方がよい.急ぐ修正ではないので,以下のことをチェックできるようにしてしばらく運用してみることにする.①ループを空回しするのに要する時間を計測する,②つねにループを2周でブレークすることを確認する.反例があれば停止する.
さて,昨日の続きに戻ることにしよう.PENDINGタグに残っているのはオン/オフを含めてあと5件だけになった.うち4件はすべて「描画矩形領域オーバーフロー」に関わるものなので,実質2件ということになるが,最初のSTRONGSHIFTREGULATIONは「すでに使われていない属性値」に関係してすでにパージを予定されている.まず,「すでに使われていない属性値@20201113」と「すでに使われていない変数@20201113」をフィックスしてしまおう.前者が10箇所,後者が11箇所だ.⇒完了した.
▲上記修正後,アプリ終了時のメモリリークが増えている.これまでは64バイトというのしかなかったが,20バイト,648バイトというのが現れた.もし,これがアプリがnewで生成したものなら,サイズ648バイトで検出できるはずだ.⇒20, 64, 648バイトに相当するメモリ取得は発生していない.メモリの取得関数は一つしかないので間違いないと思う.これには,MFCのオブジェクトは関知していないが…newを使っているところはDLLだけで149箇所ある.メモリリークはDLLだけに関係するものではないが… ⇒ソリューション全体では156箇所だ.
もし状態変化がいまの修正によるものなら,DLLに関係するものということになるが,修正をフィックスしてしまったので戻すことができない.⇒今朝の始業時バックアップを走らせてみた.同じ事象が起きる.つまり,気付かなかったが,もっと前から起きていた事象だ.Detected memory leaks! は2段階で起きている.後段のダンプは前から確認されていたが,前段のダンプは比較的最近のものだ.newで取り出しているMFC(など)NODULEクラス外のオブジェクトには以下がある.
- MyRichEdit 128
- tm 36
- CRichEditCtrl 128
- CBitmap 8
- CMetaFileDC 16
- CBrush 8
しかし,どれもサイズ的には一致しない.この他にnewで取得している以下のような配列がある.
- long*[segmentcnt]
- long[max- min + 1]
いずれも関数の出口で解放されている上,これを使っている関数MAXIMALGRAPH::SegmentBlockInclusionはすでに使われていない.
▲MAXIMALGRAPH::SegmentBlockInclusionは使われていないので「使われていない関数」で廃棄する.これを含めてMAXIMALGRAPHで使われなくなった関数が14個ある.CheckMergeSegment1~6は使用可能だが,SWO(SearchWrongObject)があれば代替可能と思われるので廃止する.⇒FIX完了した.
描画矩形領域オーバー時のオプションには以下がある.
- 描画矩形領域オーバーフローを無視する
- 描画矩形領域オーバーフローのとき自動的にズームアウトする
- 描画矩形領域オーバーフローのとき食み出した領域をクリッピングする
- 描画矩形領域オーバーフローのときメッセージパネルを表示する
現行では特に何もしていないのだから,(1)に該当するようにも思われるが相違点があるのだろうか?DISREGARDLIMITSIZEOVERがオフのときにはTREEVIEW::Refreshでダンプが出るようになっている.また,CtrlZoomInとCtrlZoomOutでは (TreeView->OVERSIZE) であればエラー復帰になるが,オンのときはつねに通常復帰している.VB側では戻り値によって何か動作が変わるのだろうか?いや,特に何もしていないようだ.従って,このオプションの効果はデバッグ時のダンプだけのように思われる.最後の(4)はすでに廃止されている.
(2)ではTREEVIEW::GetScrollValueからLimitSizeOverという関数が呼ばれてズーム倍率を調整しているようだ.(3)も廃止になっているので,効果があるのは(1)と(2)だけということになる.(1)はDEBUGのタグに移動し,(2)はOPTIONSということでよいのではないか?(3),(4)は当然廃止だ.「自動的にズームアウトする」という動作の効果は実際に試してみなくては分からないが,それは後日ということにしてとりあえず,デフォルトオフでOPTIONSに入れておく.これでPENDINGタグは空になった.
いくつかの項目をOPTIONSからSPECIFICATIONに移した.たとえば,「描画オブジェクトのリサイクルシステムを用いる」や「極大グラフ検定を実施する」などで,これらは裏面も実行可能ではあるが,実際にはオフに設定する予定はないという意味では「仕様」と見るのが自然であるからだ.というか,OPTIONSでデフォルトONであるような項目はすべてSPECIFICATIONとみなすべきだろう.
つまり,OPTIONSに残るのはデフォルトOFFの項目だけということになる.この中には「完全被参照リスト管理を実行する」や「SIMPLEGRAPHのattributeを廃止」がある.「結婚枠を折り畳む機能をサポートする」のように実装されていないオプションも便宜的にOPTIONSに収納しておこう.デフォルトOFFで現在OPTIONSに入っているものとしては,これらの他に以下がある.
- 印刷出力では連結線分・罫線を太線で描画する
- 単位家系図を廃止して拡張Z木図をサポートする
- 描画矩形領域オーバーフローのとき自動的にズームアウトする
(1)と(2)に関しては出荷時に再検討するというのでよいと思うが,(2)の「拡張Z木図」というのがよくわからない.Z木図というのはもともと多系統図だったはずだ.「拡張Z木図の場合は上流系の兄弟ノードを含む」という記述がある.また,2016-05-24 確定として「拡張Z木図を廃止して姻戚関係図をサポートする」とある.現行ではどうなっているのだろう?現行では親族範囲は7種で
- 標準家系図
- Z木家系図
- 直系血族図
- 傍系血族図
- 直系親族図
- 傍系親族図
- 法定親族図
となっている.拡張Z木図も姻戚関係図も出てこない.2018-03-26には「姻戚関係図を直系親族図に仕様変更」とあるので,現在の直系親族図がそれに該当するもののようだ.
▲ビルドしようとすると以下のパネルが出てくるようになった
書き加えた部分を削除しても変化しない.mmm… 分かった.✗(バツ)という文字を使ったためだ.X(乗算記号)なら通る.
姻戚関係図というのは多分,直系血族+配偶者の直系血族だったと思う.親族にはこれに血族の配偶者が加わるので,直系親族図というのは
直系親族図=直系血族+直系血族の配偶者+配偶者の直系血族+配偶者の直系血族の配偶者
となっているのではないかと思う.※
※親族図メニュー→親族範囲→直系親族図のヒントを見ると「本人の直系血族(先祖系と子孫系)とその配偶者,および配偶者の直系血族=直系親族」とあるのでこちらの方が正しい.つまり,直系親族図には「配偶者の直系血族の配偶者」は含まれない.
Z木家系図=直系血族+直系血族の配偶者
だと思うが,拡張Z木図はこれに本人の兄弟姉妹とその配偶者を追加したものではないだろうか?標準家系図は,
標準家系図=本人の(もっとも遠い)先祖の直系血族+その配偶者
なので,
拡張Z木図=本人の(すべての)先祖の直系血族+その配偶者
となっていたのかもしれない.直系親族図はわたしがイメージする「親族図」にもっとも近いので,現行の仕様通りでよいのではないかと思う.EXPANDGENEALOGYで「単位家系図を廃止して拡張Z木図をサポートする」ことができるのか?見てみよう.⇒このオプションはすでに廃止されている.まぁ,上の記録から見て当然かもしれない…これでOPTIONSのデフォルトOFFの項目は5件となったが,この他にまだデフォルトでONという項目が3つある.
- メタファイルに出力する@20180312
- 同性婚をアブノーマルな婚姻とする
- 系列枠内水平スプリット検定をシンメトリ婚を持つ系列に限定する
OPTIONSにはまだ実現されていない機能を含めてもよいということになっているので,「メタファイルに出力する」をOPTIONSに含めることは妥当だが,デフォルトでONになっているという点が気になるところだ.何をやっているのだろう?なるほど,「ファイルへ出力をサポートしない@20180314」というオプションに依存しているため,現在は実行できるようにはなっていない.⇒ようやくストーリィが読めてきた.それは,こういう意味だ.つまり,
印刷ダイアローグで「ファイルへ出力」を選択した場合には「メタファイル」に出力される
ということだろう.「ファイルへ出力」を選択した場合には,通常のアプリでは*.pngファイルに出力するようになっていると思う.描画イメージはCImageで保持しているので,PNG出力することは難しくない.実際,「ファイルへ出力をサポートしない」→OFF→「メタファイルに出力する」→OFFのときは,*.bmpファイルに出力するようなコードになっている.多分BMPよりPNGの方がファイルサイズは小さくなるはずだと思うので,通常通り,PNG出力でもよいのではないだろうか?
メタファイルにこだわったのは,ビットマップではなくベクトル形式で画像データを出力したかったためだが,メタファイルを編集できる(無料)ソフトが見つからなかったためペンディングになっていたのではないだろうか?「ファイルへ出力」できないというのも不都合なので,「ファイルへ出力をサポートしない」をSPECIFICATIONから一旦OPTIONSに格下げした後,改めてファイル出力形式を再検討すべきではないだろうか?⇒「ファイルへ出力」をサポートし,とりあえず,BMPに出力できるようにしておこう.この場合は「メタファイルに出力する」はOFFになるから,OPTIONSに留まる資格が維持される.
「同性婚をアブノーマルな婚姻とする」はONになっているが,その内容はかなり疑わしい.ゼルコバの木の初期バージョンというか,かなり最近までは異性婚以外はすべてエラーとして処理され,誤入力した場合には自動的に性別が整合するように補正するような仕組みまで組み込まれていたのだが,さすがに時代の潮流には逆らえずかなりルーズな扱いにはなってきている.従って,「同性婚をアブノーマルな婚姻とする」ONというのはかなり疑わしい.何をやっているのか見てみよう.
結婚リンクにはabnormalsexという属性があり,「配偶者性別に矛盾がある」場合つまり,同性婚の場合にはONになるという仕掛けだ.このabnormalsexという値が真の場合には「結婚点」の形状が変化するようになっている.具体的には,とここまで書いたところでサンプルを作ろうとしてエラーになった.⇒下記▲参照
結婚点は形状が違うというより,塗りつぶしの色が異なるだけのようだ.つまり,白と黒の中間色のグレーで表示されている.これはかなりわかり易いような気がする.
結婚点の白・黒は必ずしも女性・男性を意味するものではない.結婚連結線はあるカードとその配偶者を連結する水平線で,配偶者が複数ある場合には本人(重婚者)側が黒,配偶者側に白が与えられる.この色別はその連結線の所有者が誰かを示すためのもので,そのカードが本人ポジション(親の子ども枠)にあるか,配偶者ポジション(配偶者の親の子ども枠)にあるかには関わりがない.
「同性婚をアブノーマルな婚姻とする」という表現はややどぎつい印象を与えるかもしれないが,結婚点をグレー表示すること自体は穏便な表現になっていると思われるので,このオプションはSPECIFICATIONとしてよいと思われる.ただし,今回のセッション中に再現手順はまだ確立していないが,親子関係を設定しただけで女性が父親になってしまう例が複数発生している.これは明らかに予定されていない動作であり,誤動作と見るしかないので,バグとして追いかける必要がある.
▲下図のような家系図を入力中,GIRLの父母MAN+OTHER MANをOTHER MAN+MANに書き換えて登録で停止した.
このエラーが同性婚に関わりがあるのかないのかは不明.BUG20-11-14 22-23-24.ZELで再現できる.エラーパネルをOKで閉じるとGIRLのカードには父:OTHER MAN, 母:WOMANが残っているが,親子連結線は描画されていない.母の欄にMANと記入したのにWOMANとなっているのは,入力氏名の探索にあいまい検索を使っているため,MAN→WOMANを第一候補として登録したものと思われる.
GIRLで並び替えると下図のようになる.
できの悪い図面だ.MANが多重になってしまっている.こんな簡単な作図ができないようでは,まだまだ先が遠いという感じがしてしまう…この障害は再現できるので,先に残ったOPTIONSのデフォルトONの項目を片付けてしまおう.「系列枠内水平スプリット検定をシンメトリ婚を持つ系列に限定する」というやつだ.どうなっているのか見てみよう.TRIBEBOX::CheckInnerSplitの入口で(!SymmetryCount && !TooYoungCount)の場合は単にゼロ復帰しているというだけだ.つまり,その系列内にフロート婚と呼ばれる特殊婚が存在しない場合は処理をパスするというフローになっている.これで特に問題は生じていないように思われるので,現状でFIXでよいのではないだろうか?
これでPENDINGタグはデフォルトでON/OFFに関わらず完全に空になった.つまり,「PENDINGゼロという目標」を達成することができた.その代わり,OPTIONSには「未完成のオプション」が含まれることになったが,これらはONにしない限り作用することはないので放置されたとしても安全だ.しかし,INCOMPLETEにポジションを移した項目がかなりある.これらはINCOMPLETEというより,説明にやや疑義があるというもので,動作確認を含めた精査が必要だ.全部で8項目あり,うち「直属系列落ちを無視する@20181001」を除く7つの項目はすべてデフォルトONになっている.
- SELECTFOREFATHER IsFurtherのオプション
- 配偶者の性別不問とした 動作に疑問がある
- WriteNonStopSampleListを一時停止 WriteNonStopSampleList
- 衝突検定で計算誤差を許容する CheckIncidentalCollision
- ここでは直属系列落ちを許容する SolveTribeCollision
- 直属系列落ちを無視する SolveBondedTribeCollision
- MakeYokogakiBoxをパス TITLEBOX::SetDispParm
- NAMEBOX:Drawへ移動 意味不明なところがある
デフォルトOFFの「直属系列落ちを無視する」から見てみよう.この分岐はTRIBELIST::SolveBondedTribeCollisionに置かれ,OFFの場合にはDEBUG_NEVER (tribe->IsDirectSubTribe())を実行するようになっている.つまり,IsDirectSubTribeで停止するようになっている.ということはIsDirectSubTribe=直属系列落ちを意味すると考えて間違いないだろう.つまり,現状は「直属系列落ちなら停止する」という動作になっている.SolveBondedTribeCollisionという関数の目的は「すべての束縛系列の衝突を検査し修復する」ということだ.束縛系列に対して,自由系列というのがあり,それぞれがブロックを構成している…
束縛系列は(BONDEDTRIBE|MAGARIHOSEI|SPOUSESENZO)のいずれかの属性を持った系列と定義される.
- BONDEDTRIBE すべての下位系列と交叉しかつ上位系列と交叉している系列
- MAGARIHOSEI 先祖曲がり補正を受けた系列(スプリット検定をパスする)
- SPOUSESENZO BTW左手本人が系列先祖でかつ系列優先ノードの特殊BTWに関わる系列と左手本人およびその結婚枠
かなり難解だが,自由系列というのはおそらく主系列とそのブロックに直接接触していない系列のことだろう.始系列を除くすべての下位系列は主系列に従属するという関係にあるから,この関係を枝とする木を構成する.しかし,系列は大雑把に言って右から左に水平配置されるので,いわば切り倒した木を薪にして並べたような状態になっていると考えられる.これはそれ自体一種のトポロジーソーティングのようなものになっていると考えられるが,それをどうやって解決しているのだろう?IsDirectSubTribeという関数が返しているのは,
(MAGARIHOSEI|BOTTOMEMPTY|SPOUSESENZO|HASNOMINOR)
という値だ.新たに2つの属性が出てきた.
- BOTTOMEMPTY 最下段世代枠が空で最下段世代に消去された系列優先仮ノードが存在する系列
- HASNOMINOR 始系列を除き下位系列を持たない系列
直属系列に関しては次のような記述がある.
以下のような系列をその主系列の直属系列とする
①下位系列を持たない系列(付帯系列)
②最下段世代枠が空で最下段世代に消去された系列優先仮ノードが存在しかつ,付帯系列以外の下位系列を持たないような系列
上の定義に従えば①はHASNOMINOR,②はBOTTOMEMPTYでかつ,HASNOMINOR以外の下位系列を持たないような系列となる.IsDirectSubTribeにはBOTTOMEMPTYやHASNOMINORが含まれているところから見ると,直属系列落ちというのは,直属系列でなくなるというより,「直属系列の状態になる」のように汲み取れる.束縛系列にはMAGARIHOSEIとSPOUSESENZOが含まれているから,「束縛系列の状態から直属系列の状態に変化する」のようなニュアンスが感じられるがあまり正確ではない.
この操作に関係する属性は5つあるが,そのうちHASNOMINOR(付帯系列)だけは動的に変化する可能性はないと考えられる.(系列参照関係は動的に変化し得るので絶対にないとは言い切れない…)おそらく,この図法では直属系列と呼ばれるものをできる限り主系列の近傍に配置するというストラテジーを考えているのだろう.もう少し読まないと何をやっているのか理解できないが…