スタティックライブラリでnew/deleteをオーバーライドした場合

[戻る]
keiz 2010/04/09(金) 17:11:49
VC++(VS2008)、MFC(SDI,DocViewあり)で開発しています。
ソリューションには、

・スタティックライブラリプロジェクト(CMN.lib)
・アプリケーションプロジェクト(Hoge.exe)

があります。

このCMN.lib内で、newとdeleteを以下の形でオーバーライドしました。

void* operator new ( size_t blocksize )
{略}
void operator delete ( void* block ) throw()
{略}

Hoge.exeの初期化処理、MFCですのでCHogeApp::InitInstance内で、

(1) int a = new int;
とすると、ステップイン実行でオーバーライドしたnewへ飛ぶのが確認できます。
しかし、

(2)     CSingleDocTemplate* pDocTemplate;
    pDocTemplate = new CSingleDocTemplate(
        IDR_MAINFRAME,
        RUNTIME_CLASS(CSMViewerDoc),
        RUNTIME_CLASS(CMainFrame),       // メイン SDI フレーム ウィ
ンドウ
        RUNTIME_CLASS(CSMViewerView));

(MFCの初期化コードにデフォルトで書かれる内容)

上記のところでステップ実行すると、通常のnewへ入ってしまいます。

また、上記現象はDebug版の場合ですが、Release版だとオーバーライドしたnewにきてい
るようですが、解放がなぜか通常のdeleteに行ってしまったりします。

当然ですが、Hoge.exe内の下記define(自動生成)はコメントアウトしてあります。

/*
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
*/

常にオーバーライドしたnewで処理をさせるには、どのようにすればいいかお知恵をお貸
しください。
ライブラリでオーバーライドするのはよろしくないなど、あったりしますか?

keiz 2010/04/09(金) 17:42:35
追記です。

デバッグモードだと、CObject::newに入るクラスがあるようですね。
これのせいですべてのnewを自前のnewに置き換えられていないようです。。。

目的を遂げるにはどうすればよいか、お知恵ありましたらよろしくお願いします。

tetrapod 2010/04/10(土) 09:16:50
C++ 言語規格書で次のように決まっている。
5.3.4 new 式
9 new 式が :: で始まる場合、大域割付関数が検索される。そうでない場合、
・割付型がクラス T または T の配列である場合 T のスコープ内から割付関数を探す
・先の検索でみつからないか、クラス型でない場合は大域割付関数を探す。
3.7.3 動的記憶域期間
2 処理系はデフォルトの大域割付関数、大域解放関数を用意する。
一部の大域割付・解放関数は上書き可能なものもある (18.4.1)

ということで・・・
クラスのメンバー関数として operator new を持っているクラスを使っているなら
大域割付関数を上書きしても *そのままでは* 使われないのが仕様。
※ delete も同様。

サンプル
#include <iostream>
#include <stdlib.h>

struct hoge {
    void* operator new(size_t sz) {
    std::cout << "operator new hoge(" << sz << ")\n";
    return malloc(sz);
    }
    virtual ~hoge() { std::cout << "hoge::~hoge\n"; }
    hoge() { std::cout << "hoge::hoge\n"; }
};

struct piyo: public hoge {
    ~piyo() { std::cout << "piyo::~piyo\n"; }
    piyo() { std::cout << "piyo::piyo\n"; }
};

int main() {
    hoge* p=new piyo; // ここを ::new piyo; にしてみるテスト
    delete p; // ::delete にしてみるテストの際には operator delete 要実装
}

MFC ソースの中で new してるものについては対処の仕様が無いね・・・

keiz 2010/04/16(金) 10:42:48
tetrapodさま、レスありがとうございます。返答遅くなりすみません。
いろいろ追っていって、

>MFC ソースの中で new してるものについては対処の仕様が無いね・・・

という結論に私も達しておりました。
これが規格通りなのですね。
MFCを使わない方向で上司と相談します。
ありがとうございました。

keiz 2010/04/16(金) 13:30:31
[[解決]]
一応、ご回答で納得したので解決にしておきます。

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