動作環境
C++ Builder XE4
変更内容
- 四台の装置との通信ソフトをベースに一台の装置との通信ソフトを作成
- static const int定義を4から1に変更
実行すると以下となる。
関連
C++ Builder > Error: モジュール '何がしのプログラム.exe'のアドレス0044392Eでアドレス000005B5に対する読み取り違反がおきました。' > 原因の特定 | 原因
リンク先の方法で原因を特定しようとしたが分からなかった。
VCLのソースにリンクされるだけで、自前実装のソースのエラーは特定できない。
原因の特定方法 (今回の思いつき)
- gitでチェックインしておく
- 元に戻せるように
- 二..四台目関連のフォームコンポーネントを削除
- IDEでビルド
- 削除コンポーネント関連のエラーが出るので、削除していく
- 削除後ビルド
- 実行できた
- gitで差分を見る
- 関連関数のリストアップ
- gitで元に戻す
- 手順5でリストアップした処理を逐次コメントアウトしビルド・実行
- エラーが出なくなる部分が問題箇所
問題の箇所
void __fastcall TXXXForm::SetTPanelPointers(TPanel *srcPtr, int DEVidx, int panelIndex)
{
m_panelPointers[DEVidx][panelIndex] = srcPtr;
}
上記が問題。インデックスの範囲をチェックする実装がもれている。
加えて、下記の処理があるために、DEVidx=1以降でメモリ関連エラーが発生したということだった。
SetTPanelPointers(P_DEV1_group1, /* DEVidx=*/ 0, /*panelIndex=*/ 0);
SetTPanelPointers(P_DEV1_group2, /* DEVidx=*/ 0, /*panelIndex=*/ 1);
SetTPanelPointers(P_DEV2_group1, /* DEVidx=*/ 1, /*panelIndex=*/ 0);
SetTPanelPointers(P_DEV2_group2, /* DEVidx=*/ 1, /*panelIndex=*/ 1);
SetTPanelPointers(P_DEV3_group1, /* DEVidx=*/ 2, /*panelIndex=*/ 0);
SetTPanelPointers(P_DEV3_group2, /* DEVidx=*/ 2, /*panelIndex=*/ 1);
SetTPanelPointers(P_DEV4_group1, /* DEVidx=*/ 3, /*panelIndex=*/ 0);
SetTPanelPointers(P_DEV4_group2, /* DEVidx=*/ 3, /*panelIndex=*/ 1);
今後の予防策
SetTPanelPointers()内において「DEVidxの範囲外エラー」、「panelIndexの範囲外エラー」チェックを追加する。
範囲外エラー発生時にはデバッグウィンドウなりにエラーメッセージが表示されるようにする。
void __fastcall TXXXForm::SetTPanelPointers(TPanel *srcPtr, int DEVidx, int panelIndex)
{
if (DEVidx > kNumDEV) {
String msg = L"XXXUnit: Line985 > Error: [DEVidx] out of range";
OutputDebugString(msg.c_str());
return; // error
}
if (panelIndex > kNumPanel) {
String msg = L"XXXUnit: Line990 > Error: [panelIndex] out of range";
OutputDebugString(msg.c_str());
return; // error
}
m_panelPointers[DEVidx][panelIndex] = srcPtr;
}
実際に実行すると、IDEにて下記の表示がされるようになった。
デバッグ出力
デバッグ出力: XXXUnit: Line985 > Error: [DEVidx] out of range プロセス XXX.exe (1364)
デバッグ出力: XXXUnit: Line985 > Error: [DEVidx] out of range プロセス XXX.exe (1364)
デバッグ出力: XXXUnit: Line985 > Error: [DEVidx] out of range プロセス XXX.exe (1364)
デバッグ出力: XXXUnit: Line985 > Error: [DEVidx] out of range プロセス XXX.exe (1364)
同じような失敗をしていそうなコードを探して対処する。
技術的負債
(追記 2017/10/06)
およそ700の関数のうちで13の関数で同じ失敗をしていた。
対策をしておいた。
将来的にstatic const int変数を変更時に発生する「技術的負債」を自分が作ってしまったのは残念ではある。
一つ一つの関数作成時にもっと集中して行わないといけない。
@nonbiri15 さんの品質は作りこまないかぎり実現できない
は金科玉条として胸に叩き込んでおいた方が良さそうです。