また条件コンパイルマクロの集計が合わなくなった

comdebug.hでCOMDEBUG: タグ付けの誤りが見つかったので修正した.これでまた条件コンパイル定義文の集計が合わなくなった.原因を調べる必要がある.正規表現で値なし定義文を検索した結果は131件で変わらない.COMDEBUG: は1個減って27個になっている.どこかで間違えているはずだ.⇒昨日はフィルタリングした状態では連続データの入力(ナンバリング)ができなかったが,メニューから実行する方法がある.また英語版に戻しているが,Edit→Fill→Seriesが使える.ただし,実行する前に複数セルを選択しておかないとコマンドが出てこない.⇒以下の手順で簡単にチェックできる.

  1. VSで値なし定義文を正規表現を使って検索し,テーブルに出力
  2. (1)をOpenOfficeに読み込み,COMDEBUG: でフィルタリング
  3. VSでCOMDEBUG:で全文検索し,テーブルに出力
  4. (3)を(2)の後ろに貼り込み
  5. (4)をソートして,ダブっていない行を探す

いや,おかしい.COMDEBUG:で検索した結果も27で合っている.上の手順で比較しても完全に一致している.ということは別のタグで不一致ないし増減が起きていると考えるしかない.調べてみよう.SPECIFICATION:は16で昨日と同じだ.OPTIONS:(11),DEBUG:(23),VERIFY:(5),TEST:(11),LOCAL:(10),_H_ (27)ですべて同じだ.トータル130で1個過不足がある.つまり,#define文の方が多いということになる.これを見つけるのは容易だ.タグがついてないものを探せばよい.あった.HOSTCMD.H冒頭のマクロだ.

#if !defined(__HOSTCMD_)
#define    __HOSTCMD_

これは,

#if !defined(__HOSTCMD_H_)
#define    __HOSTCMD_H_

のように書かれなくてはならない.ヘッダファイル冒頭のマクロは以下の式で正規表現のオプションで検索している.

検索:#define.*_H_         (H)ヘッダファイル冒頭の定義文を検索

これで_H_の個数は28となり,トータル131で完全に一致した.昨日の数字が合っていたのも,単なる偶然ということになる.やれやれ…

ダメだ.まだ合っていない.上記の検索:#define.*_H_の行が検索結果に含まれてしまっている.これを除くと27個,まだ総数ではあっていない.この行がヒットしないように検索キーを次のように変えてみた.

検索:#define\s+.*_H_   (H)ヘッダファイル冒頭の定義文を検索

これで件数は27という正しい数字になったが,タグ付きの総数は130で定義文の個数131と合わない.ヘッダファイル定義のミスがもう1件あった.Lineage.hで_LINEAGE_Hになっている.⇒これで完全に一致した._H_の個数は28が正しい.

さて,「制御が渡らないコードです」の問題を片付けなくてはならない.昨日のログでは,後付けで「※理由は簡単,STOPで例外をスローしているのは「公式版」だけだ」としているが,リリースモードでFORMALVERSIONとしてもこの警告は表示されない.リリースモードとデバッグモードでは警告の出方が多少異なるので「そんなものか」とも思うが,普通はリリースモードの方が厳格になっているのに,その逆というのが納得いかないところだ.

警告レベルを下げるなどの対処法は芳しくないので,昨日述べたように,例外をスローするのはASSERTIONに限定することにする.⇒実装してみたが,悪くないように思われる.Stopはどうだろう?デバッグモードではSTOPと同じ効果だ.内部でSTOPを呼び出している.Stopは引数で文字列を渡せるので,STOPより詳細な情報を得ることができる.公式版の場合はデバッグ時と同様の動作でよいのではないか?Stopは関数でマクロではない.どこかでデータ退避.ZELへの書き込みが発生している.⇒呼び出されてはいるがパスしている.SAVERESCUEFILEがデバッグ時しか有効でないためだ.なぜだろう?理解できない.

公式版ではalartprintでパネルを表示しないようにしたので,STOPと_STOPを公式版だけ別扱いする必要はなくなった.この2つは共通定義でよいのではないか?⇒いや,そういう訳にはゆかない.デバッグモードでは停止しなくてはならない.⇒STOP,_STOP,Stop の動作はまずまずなのではないかと思う.デバッグモードではある程度情報を取得できるようにした.ただし,「_DEBUGマクロを未定義にする@20170811」ではほとんど何の情報も得られない.アプリは停止しないのでまるで問題なく走っているかのようだ.

ASSERT_NEVERを試してみた.なんとあの懐かしいパネルが飛び出してきた.標的型攻撃を受けてお払い箱になっていたあのカマキリだ.

image

しかし,このあとが相当悪い.パネルを開くと同時にユーザ会サイトのバグレポートにアクセスして「インターネットに接続されていません」になるのはよいとしても,パネルを閉じた後にSTOPパネルを2回開いたあと,以下のパネルが順番に出る.

image

image

image

image

image

新規ファイルのオープンに失敗した場合には打つ手がないのでアボートするというのでよいと思うので,新規ファイルだけは作れるような場所で例外が発生するようにしてみよう.PARTIALNAME:PartialMapCommandに例外を仕掛けてみたが,パスが通っていないようだ.どこかで握りつぶされている.mmm…今度はパネル1枚出さないでアプリ終了してしまった.この例外は全くトラップされずにストレートにGCまで戻ってしまっているようだ.

上の現象は再現できない.確かにmZelkova::mPartialMapCommandにはエラートラップが仕掛けられていない.GCでは61個の関数にエラートラップが設置してあったのだが,肝心なところが抜けていた.エラーを返してやっても以下のパネルが出るだけだ.

image

これはVB側の判断でエラーで帰るとこのパネルを出して抜けるようになっている.ここでは,⇒「検定に失敗しました」を出してもらいたいところなのだが…検定に失敗しましたは,InitializeDisplayで出しているものだ.系統並び替え実行後はかならずここを通るので,ここで「検定に失敗しました」を出すのは妥当だろう.ユーザは何度も「部分図タイトルを選択してください」が出れば,おかしいと思って問い合わせしてくるかもしれない.しかし,その前にユーザにASSERTIONで失敗したということが伝えられていなければならない.

GCではエラーをキャッチしてはいるが,エラーの種別には無頓着なのでエラーコードを取り出すこともできない.これはやはりDLL側で受けるしかないのではないだろうか?GCとDLLを接続する関数は1対1になっているので,対応するにはすべての場所で個別対応するしかないが,幸い部分図はコマンド処理になっていてすべての操作が一つの関数を通るようになっているので,対応は容易だ.

PARTIALNAME::PartialMapCommandの後半部,実際にコマンドを実行している部分にはすでにトラップは仕掛けられているので,前半部にだけ掛けてみよう.おかしい.なぜだろう?キャッチできない.どこかでSTOPしていることは確かだが,FORMALVERSIONなので停止しない.⇒エラートラップにSTOPが置いてあった.

ここでもう一度例外をスローしてそれがGCに入ってくる.例外をそのまま転送するというのはそれでよいとしても,ここで何らかの処理をしないと何が起きているのか分からない.一番早いのはASSERT_NEVERで直接処理することだろう.ASSERT_NEVERの内部で処理するとしたら,マクロではなく関数化した方がよいのではないだろうか?しかし,関数化してしまうと,障害が発生した場所が分からなくなる.関数名くらいなら渡してももよいが…⇒マクロはマクロとして残して内部処理の部分を関数化しておくというのが扱い易いのではないか?情報はマクロから関数の引数で渡してやればよい.⇒それがよいもしれない.

ERR_ABORTEXPERIMENTというのがすでにある.何をやっているのか見てみよう.⇒こんなことがあるのではないかと思っていたが,やっぱりエラーコードのダブリがあった.ERR_CARDTABLEOVERとERR_SHOWUNDERWEARがかち合っていた.エラーコードは一応カテゴライズされているのだが,なぜか大きい番号があちこちに散らばっている.⇒ERR_SHOWUNDERWEAR,ERR_ABNORMALGENEGAP,ERR_ABORTEXPERIMENTなどをキャッチしたときには,例外を先送りしている.ERR_ABORTEXPERIMENTをキャッチしている2箇所で,ERR_ABORTPROCも同じ扱いになるようにした.

PartialMapCommandの前半と後半の2つのトラップは一つにまとめてよいと思う.一応の段取りはできたが,最初のエラーパネルが多重に出てくる状態を再現できるだろうか?例外を部分図のロードに仕掛ける前だから,MakeUpTreeかないしその前と思われる.⇒場所が見つからない.上記でエラートラップ2箇所では例外を先送りするように修正しているので,処理されているのかもしれない.⇒少なくとも処理されずにゼロ復帰している箇所はある.すべてのエラートラップで例外を先送りするようにしておく必要がある.catchで検索すると207箇所もある.整数型以外のエラーをキャッチした場合には警告パネルを出すようになっているので,整数型だけ見ればよいと思う.

THROWFATALERRORというマクロを作って,ERR_SHOWUNDERWEAR,ERR_ABNORMALGENEGAP,ERR_NOMEMORY,ERR_ABORTEXPERIMENT,ERR_ABORTPROCでは例外を先送りするようにしてみよう.整数型エラーをキャッチしているところは74箇所ある.⇒TRASHCAN::throwCanのようにすべての例外を投げ出しているところはそのままとする.⇒対応修正完了した.

▲potential.cppの707行目で例外を発生させるコードをリリース版で走らせると,COUPLING::TopologicalSortのエラー→検定に失敗しました→新規ファイルのオープンに失敗しました→プログラムを終了しますの後にどこか不明の地点で例外が発生する.

コメントを残す

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

CAPTCHA