GW前ってなぜトラブルが多発するのだろう..orz

不景気のおかげでGWは11連休だーっ!・・・と思っていたのですが、実機デバッグしてた子からの突然の内線電話「すみません、なぜかブートできなくなってしまってます」に、長期休暇の夢は露と消えました。

メモリ吹っ飛ばし系の よくある質の悪い不具合が発生で、昨日は午前様までお仕事。今起きて、寝起き頭でちょっとメモ。(最近、残業規制とかでこういう野無かったのですが、たまにはこんなのも楽しいよね)

その不具合というのですが、どうもポインタ参照している何かを手繰ってメンバアクセスすると出るアリガチなものですが、ブート時にいきなりとか、そのた色々で、確かめることが多くって調査に時間が掛かってしまいました。一応、昨日の時点で問題の除去は終わったのですが、その間に遅れたスケジュールの埋め合わせのため、GW を有給でつなげる計画はキャンセル。残念だー。

そういえば一昨年も GW中にトラブったなぁ。過去を振り返れば、冬休みとか、GW とか、「休む」って決めてるときに限ってトラブルが起きるような気が。・・・普段の行いかしら。うぅむ。


* * *


以下は半ば自分向けに、問題の内容をメモ。

class Foo : public BarModule, public BuzInterface
{

Module は仮想関数を持っていないけど実装がある、Interface は純粋仮想関数だけを持っている もの。class Foo は、テンプレートメソッドの基底クラスになるクラスで、更に継承されて使われてます。

Fooから派生したクラスは、ビルド依存関係を切りたい関係で、行儀がわるいのですが ダウンキャストをして使われています。ここがトリガーでした。

Windows PC 上で MinGW でビルドしている方(ユニットテスト)は問題なく動いてたのですが、これがターゲット環境用のコンパイラ(2.x な古いgccベース)でビルドすると、先の問題が起きました。どうやらメンバ関数へのアクセスが不正メモリアクセスになってしまう、みたいな様子。時間の関係で調べたのはココまで。

ちなみに、

class Foo : public BuzInterface, public BarModule
{

と継承の順序を入れ替えると 問題発生せず。また、BarModule に 仮想デストラクタを持たせ、vtbl を作ってあげても 問題発生せず。ふむう。

Foo が肥大化したので、リファクタリングされたことにより、このコード修正がはいりました。ターゲット機器の都合で3週間くらい実機動作出来なかったのですが、まぁWindows PC 上で動くユニットテストも通ったし、いっか、でコミット。いざ実機でまとめて・・の段で、小まめな確認をちゃんとやらなかったリスク分のしっぺ返しはきちんと頂いてしまった次第です。

もちろんこんなわかりやすいクラス名だったわけじゃなくって、Bar を調べてみたら仮想関数が一個もないのに気付いたのです。

仮想関数のないクラスを継承するのは基本的には良くないですし、実装が欲しいだけだったら委譲におきかえるべき、というはそうなのです。ただ、それはそれとして、C++ 的にドボンではないと思っていたので(もしかしたら未定義動作になっちゃうのかな)、そこの白黒はあとでちゃんと勉強しないと。