▲BUG20-12-20 00-37-44.ZELの全体図を#229 式部卿宮の北の方で開いてアプリ終了して,Nringの残留オブジェクトが9件発生している.いずれもfreeblockだ.⇒freeblock::ReleaseFreeBlockがどこでも実行されていない.EraseFamilyTreeで実行していたはずなのだが… 条件コンパイルをフィックスする時点で消してしまったのだろうか?2020-12-15のバックアップを見ると,#ifdef 廃止@20201213 となっている.しかし,これは間違っている.
freeblock自体はnoduleオブジェクトの一種だから,ゴミ箱に入っていればゴミ箱の廃棄で削除されるが,アクティブなオブジェクトはCOULPINGとは別建てで管理されている.freeblockはリスト管理されていて,リスト先頭はグローバル変数のtopblockにある.この管理方式はあまりよくないと思う.ゴミ箱がCANというオブジェクトで管理されているように,freeblock管理の代表オブジェクトを定めて,CANと同格の位置に設置するようにした方がよい.しかし,その前にまず,Nringの残留の問題を片付けておこう.
freeblockは固有データ部にフリーメモリブロックを持つオブジェクトで,削除された場合は通常のオブジェクトと同様にゴミ箱に入るのでリサイクルは可能だが… Nringにどんなオブジェクトが残っているのか調べてみよう.以下のfreeblockが残留している.#879から連番で#887までの9個で,すべて個人記録ページだ.このアドレスはCARDLINK:cardbase.notepageに格納されている.CARDBASEに格納されている以下のリンクはすべてfreeblockで取得されたものと思われる.
CBitmap *cBitmap; // MFCビットマップ
BITMAPINFO *bitmapinfo; // カード画像DIビットマップ
char *notepage; // ノートページデータへのポインタ
これらのリンクはベタ参照であり,noduleオブジェクトとして管理されている訳ではないので,オブジェクトが削除されても自動的には削除されないから,どこかで明示的に削除する必要がある.画像イメージや記録ページデータなどはファイルに属するものだから,ファイルクローズで廃棄でよいのではないだろうか?
いや,少し違うのではないか?CARDBASEに載っているものは,CARDBASEのデストラクタで始末するべきだ.この意味では,@20201213 の決定の方が正しいような気がする.⇒現行では~CARDBASEでは何もしていない… ⇒ここでcBitmap,bitmapinfo,notepageを削除するようにしてみよう.
どうもこのCARDBASEのnotepage管理はあまり整っていないように思われる.notesizeがCARDBASEの下のCARDATAに入っている.しかも,ここにはもう一つ別のCBitmap*cbitmapというリンクまである.どうなっているのだろう?⇒CARDATAは外部とのインタフェース用,CARDBASEはデータ管理用という差があるのかもしれないが… メモリ管理ということは念頭になかったように思われる.
freeblock::delmem_((void**)¬epage, carddata.notesize);
上記で一応メモリからの解放はできているようだが,「カウント不整合」がまた起きている.上の文が正しいかどうかも検証を要する.notepageというのはCARDLINK上のメンバー変数であり,メモリブロックを管理するfreeblockのアドレスが正しく引けているかどうかはチェックする必要がある.⇒関数の使い方を間違っている.bool freeblock:_delmem_(void **mptr)を使う必要がある.この関数を使ってカウント不整合も消えた.この関数ではサイズを指定する必要がないので,CARDBASEでサイズを押さえていないことも説明できる.
Nringの残留も解消した.CBitmap *cBitmapも同じ方法で削除しようとしたが,エラーになった.freeblock::ReleaseFreeBlockではカード写真イメージを解放するのに,DeleteBitmapImageという関数を使っている.CBitmapでは「ビットマップを破棄」するという操作が必要だ.
cBitmap->DeleteObject(); // ビットマップを破棄する
delete cBitmap;
しかし,delete cBitmapで削除できるということは,このオブジェクトはfreeblockを使っていないのだろうか?⇒確かに,new CBitmap; で生成されているようだ.CARDBASEが保持するオブジェクトに関してはこれでクリアできた.RTFを使っているところはカードの記録ページの他にもあったはずだ.タイトル履歴とか… ⇒調べてみよう.freeblockのMMTYPEには以下がある.
- MM_NODULE, 未使用
- MM_NOTEPAGE, カード記録ページ CARDLINK::cardbase.notepage
- MM_CARDIMAGE, カード写真イメージ CARDLINK::cardbase.bitmapinfo
- MM_CHUNKFILE, 記録ページ読み込み用バッファ FAMILYTREE::chunk.FILEBUFF
- MM_BUNSFILE, データ読み込み用バッファ BUNSFILE::bunsbuff
- MM_QUICKDB, カードテーブル項目名 QUICKDB::itemtable[maxitem].itemname
- MM_TEMPLATE, 廃止
- MM_TITLEINFO タイトル履歴 TITLELINK::TitleInfo.Rtfbuf
タイトル履歴はTITLELINK::Disposeで削除しているので問題ない.CHUNKFILE chunkを持っているのはFAMILYTREEではなくCOUPLINGだ.chunk.FILEBUFFの解放は~CHUNKで実施すべきだろう.⇒いや,やっている.~BUNSFILEでもbunsbuffの解放は実施されている.~QUICKDBにも同様に措置されている.一応これですべて押さえたということになるだろう.MM_TEMPLATEは完全にソースからパージしてよいと思う.⇒いや,REVISIONの古いデータを読み込む場合に必要になるので残しておくしかない.
バックアップも取ったので,最近の修正をフィックスしておこう.以下の3件がある.
- Nodule:numberを廃止する@20201218 24箇所
- COUPLING:TemplateBuffを廃止する@20201219 13箇所
- 優先実ノードは本人・配偶者を問わない@20201221 2箇所
▲ZTシステム構成図7.ZELの全体図を#5 pagesetupで開いて,基準ノードを削除→UNDOで参照リストと参照カウントの不一致が発生する.⇒MARGLINK:#570のスロット20からの参照が参照リストに登録されていない.つまり,Sansyoを呼び出さない参照の書き換えが実行されているように思われる.
UNDONODE:UndoCopyでは冒頭ですべての参照をリセットしているが,その後の動作は単純な上書きコピーになっている.コピーではなくSansyoの実動作で書き込まなくてはならない.⇒一応実装してみたが… これはかなり難しそうだ.