クラスインスタンスの呼び出しがおかしい

[戻る]
Sana 2008/12/05(金) 18:40:31
クラスの定義(?)でつまずいております。
現象で原因を探っておりますが
解決に至っておりません。

対処方法はあるのですが、それとは別に
どうして現状だめなのか、スルーしたくないので
ご教授いただければと思います。


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') 2008/12/05(金) 22:45:44
俺の立場では他人のプログラムで起きている不思議な現象なんてわからんので
推測だよ。

デバッグ版ならエディットコンティニューになっている可能性があるな。
部分的にしかコンパイル・リンクしなおされていないのかもしれない。
変な時はリビルドしましょう。
エディットコンティニューはすごい便利なんだけど
メンバ変数追加しただけだと再コンパイルされないことがあるのさ。

ISLe 2008/12/05(金) 23:53:31
うちはエディットコンティニュー使って無いんですけど、依存関係データベース関連の
バグなのか必要なリコンパイルがされないことはよくありますね。

Sana 2008/12/08(月) 13:17:26
[[解決]]
wclrp ( 'o')さん、ISLeさん。ありがとうございます。

変数の追加、削除を行いトレースのthisアドレスを確認してふと見るとズレが4バイトの
場合があり、もしやと思い、全ソースの検索を行ったところ、
見事に#pragma pack(push, 1)に対するpopが抜けている箇所がありました(^^;;
パディングの絡みみたいだなぁとは思っていても、後に症状が出てくると、その時点では
他で変更してることに結びつきませんでした。

どおりでオブジェクトのアドレスにズレが生じていた訳で、現象から素直に考えてみたら
普通はこれに行き着き付くよなぁと思いつつ反省…。

大変お騒がせしました。ありがとうございました。

古いスレッドには追加発言できません。