たくさんのTNotifyEventsをベクターに入れるコードがあります。
std::vector<TNotifyEvent> m_availableCallbacks;
これは、アプリケーションのメインフォームのメンバーです。フォームコンストラクターでは、イベントで埋められます。
m_availableCallbacks.push_back(ReadoutLastValue);
m_availableCallbacks.push_back(ReadoutCurrentDay);
m_availableCallbacks.push_back(ReadoutLastDay);
m_availableCallbacks.push_back(Readout7Days);
m_availableCallbacks.push_back(Readout1Month);
m_availableCallbacks.push_back(ReadoutChooseTimeSpan);
m_availableCallbacks.push_back(ReadoutAllData);
次に、このベクトルが繰り返され、ポップアップメニューを作成し、そのポップアップメニューの要素に通知イベントを割り当てるために使用されます。
これをローカルでコンパイルしても問題はありません。ビルドサーバー(TeamCity 6.5を実行している)でコンパイルすると、2番目のpush_back呼び出しに等しい行で内部コンパイラエラーが発生します。
cbprojファイルを編集して、ビルドエージェントでローカルにスマートキャッシュのプリコンパイル済みヘッダーを無効にしてみました。これにより、ビルドが成功しました。そこで、すべてのcbprojファイルからスマートキャッシュのプリコンパイル済みヘッダーを使用するディレクティブを削除し、変更をコミットしました。TeamCityにクリーンチェックアウトを実行するように指示しましたが、同じ場所で同じ内部コンパイラエラーが発生しました。奇妙なことに、失敗したコンパイルの後に新しいコンパイルを実行すると成功するため、これは非常にランダムに感じられます。
何が起こっている?私は他のC++コンパイラで関数ポインタ(自分で作成したもの)をうまく渡すことに慣れています。TNotifyEventsの内部処理が壊れていますか、それともコンパイラが不安定で簡単に壊れていますか?
TNotifyEventsを取得する他のコードを見ると、参照やポインターでは機能しないため、私はそれを試しませんでした。また、コード(コンパイル時)は意図したとおりに機能するため、問題はないようです。
アップデート:
TeamCityのログには、コンパイルを再実行して成功したときにFrontEnd.cppファイル(このコードが含まれている)がスキップされることが示されていることを追加できます。
[10:04:37]: [MakeObjs] CallTarget
[10:04:37]: [CallTarget] _CppDepCheck
[10:04:44]: [_CppDepCheck] MessageMap
[10:04:44]: [MessageMap] Skipping: ..., FrontEnd.cpp, ...
そしてそれが機能するためには、内部コンパイラエラーが発生したときにコンパイルが成功している必要があります。それ以外の場合、ファイルのコンパイルをスキップし、それでも魔法のように表示され、コンパイルされた形式で使用されるようにするにはどうすればよいでしょうか。:)
Update2
調査の結果、これはリリースモードでコンパイルした場合にのみ発生することが確認できました。リリースでは、IDEのローカルマシンでも発生します。私は次のような設定をいじってみました
- すべての最適化を無効にする
- 可能な限り最速のコードを生成する
- 外部タイプファイル
- 等々
各試行の間にビルドをクリーニングします。しかし、ICEは消えません。しかし、私はなんとか別のファイルの別の場所について文句を言うことができました。設定を以前の状態に戻しても、エラーがFrontEnd.cppファイルに戻ることはありません。このコンパイラはちょっと不安定に感じます:)
実際、私はコード全体でICEを取得し始め、何でもコンパイルできるようにするためにIDEを再起動する必要がありました。