クラスの定義(?)でつまずいております。
現象で原因を探っておりますが
解決に至っておりません。
対処方法はあるのですが、それとは別に
どうして現状だめなのか、スルーしたくないので
ご教授いただければと思います。
template <class TBase /* = CWindow */>
class CWindowImplRoot : public TBase
{
...
};
template <class TBase = ATL::CWindow>
class CWindowImplBaseT : public CWindowImplRoot< TBase >
{
...
};
template <class T, class TBase /* = CWindow */>
class CWindowImpl : public CWindowImplBaseT< TBase>
{
HWND Create(){
/*ここでデバッグ*/
}
};
template <class T, class TBase = ATL::CWindow>
class CScrollWindowImpl : public ATL::CWindowImpl<T, TBase>,
public CScrollImpl< T >
{
...
};
class CViewWnd : public CScrollWindowImpl<CViewWnd>
{
int a;
int b;
ULONGLONG ull;
};
// CCommand,CMenu,CViewWnd等はそれぞれ子ウィンドウ
class COverlapWnd : public ....
{
CCommand m_Command;
CMenu m_Menu;
CViewWnd m_View;
CStatus m_Status;
OnCreate(){
m_Command.Create();
m_Menu.Create();
m_View.Create(); // ここ
m_Status.Create();
}
};
class CMain
{
COverlapWnd m_Wnd;
OpenOverlapWnd(){
m_Wnd.Create(...)
}
};
//
// エントリー
CMain g_Dlg;
int WinMain(){
g_Dlg.DoModal();
}
m_View.Create を呼び出すのですがCWindowImpl::Create上でのthisポインタの示す位置
がCViewWndメンバを含まずCWindowImplBaseTのみとなります。
そのためCWndBase::Create上の処理でCViewWnd(class T)への参照ができておらず正常
な処理が行われなくなります。
(場合によってはATL::CWindowのメンバも初期化されていません)
いろいろ変更するとthisポインタの示す位置は合っているがトレース上だけおかしかった
り、thisポインタ自体もずれていたりします。(定義の順番で変化するため等メモリ位置
が関係しているみたいなのですが…)
CCommand m_Command;
CMenu m_Menu;
CViewWnd m_View;
CStatus m_Status;
の定義順、上記メンバ変数削除等の操作により呼び出しが不正になったりします。
そもそも発端は、CViewWnd内の変数メンバ変数を増やしところ、この現象が発生するよう
になり、現在に至っておりますが原因が掴めておりません。
また、CViewWndの定義を一度クリアし、再度定義を追加していってどの部分が影響してい
るか確認したところint 変数はいくつ追加しても問題ありませんが、なぜかULONGLONG を
追加した時点でアウトのようです。
CViewWndをnewで作成する、またはCOverlapWndのスタティッククラスとして作成すると
問題がなくなり、ウォッチ上でもCViewWndおよびCWindowImplBaseTのthisポインタを示し
ています。
環境は VC2008 & WTL(SDK)です。
俺の立場では他人のプログラムで起きている不思議な現象なんてわからんので
推測だよ。
デバッグ版ならエディットコンティニューになっている可能性があるな。
部分的にしかコンパイル・リンクしなおされていないのかもしれない。
変な時はリビルドしましょう。
エディットコンティニューはすごい便利なんだけど
メンバ変数追加しただけだと再コンパイルされないことがあるのさ。
うちはエディットコンティニュー使って無いんですけど、依存関係データベース関連の
バグなのか必要なリコンパイルがされないことはよくありますね。
wclrp ( 'o')さん、ISLeさん。ありがとうございます。
変数の追加、削除を行いトレースのthisアドレスを確認してふと見るとズレが4バイトの
場合があり、もしやと思い、全ソースの検索を行ったところ、
見事に#pragma pack(push, 1)に対するpopが抜けている箇所がありました(^^;;
パディングの絡みみたいだなぁとは思っていても、後に症状が出てくると、その時点では
他で変更してることに結びつきませんでした。
どおりでオブジェクトのアドレスにズレが生じていた訳で、現象から素直に考えてみたら
普通はこれに行き着き付くよなぁと思いつつ反省…。
大変お騒がせしました。ありがとうございました。