none
MFC をスタティックリンクするプログラムで、ランタイムタイプ情報( typeid )を使用するとメモリリーク する RRS feed

  • 質問

  •   こんにちは。

     

      VisualSdtuio 2005 でコマンドラインプログラムをウィザードで作成し、プロジェクトのプロパティで

    「全般」の「MFC の使用」の項目を 「スタティック ライブラリで MFC を使用する」に変更し、以下のように

    typeid を使用するとメモリリークが発生します。

     

    int _tmain( int argc, TCHAR* argv[], TCHAR* envp[])
    {
       int nRetCode = 0;

     

       // MFC を初期化して、エラーの場合は結果を印刷します。
       if( ! AfxWinInit( ::GetModuleHandle( NULL ), NULL, ::GetCommandLine(), 0 ))
       {
            // TODO: 必要に応じてエラー コードを変更してください。
            _tprintf(_T("致命的なエラー: MFC の初期化ができませんでした。\n"));
            nRetCode = 1;
       }
       else
       {
            puts( typeid( ::AfxGetApp()).name()) ;
       }

     

       return nRetCode ;
    }

     

    マイクロソフトのサイトに、

     

    「FIX: ランタイム タイプ情報を使用することによりメモリ リーク レポートが発生することがあります。」

    http://support.microsoft.com/kb/140670/ja


    というドキュメントを見つけましたが、対象が VC4.0 と VC4.1 と古くVisualSdtuio 2005 でも

    発生し続けるものかわかりません。ドキュメント同様に無視できるものならいいのですが、

    デバッグ情報にメモリリーク情報として出てしまうので、対処方法がありましたら教えて

    頂けないでしょうか ?

     

     

    2007年10月11日 6:36

すべての返信

  • KB については、探していないので何とも言えませんが、ちょこっと潜ってみた感じでは、リリースのタイミングの問題で、メモリーリークが報告されているように思われます。

     

    動作としては、type_info オブジェクト(typeid() で返されるオブジェクト)に、必要になったタイミングで名前を malloc してくる格好になっているので、結果としてメモリーリークが出てしまうということになりますね。

     

    実際は、プロセス解放のタイミングでオブジェクトも破棄されるので問題はないといえます。

     

    が、どうしても取り除きたいのであれば、typeid を使っても name() は呼ばないなどを行わないと無理だと思います。

    2007年10月11日 8:40
  • 早々のレスありがとうございます。

     

    自分なり調べてみたのですが、とくに解決方法はなさそうです。

    特に問題なさそうなのでこのまま使いようにするか、typeid の name に変わる別の方法を模索したいと思います。

     

    2007年10月11日 11:39
  • 通常、オブジェクトの型が特定のものかを typeid で判断するのであれば、

    CHoge hoge;

     

    if( typeid( hoge ) == typeid( CHoge ) ){
     // 同じ時の処理...

    }

    という形になるのではないかと思います。

     

    また、MFC 限定でなおかつそのクラスが CObject の派生クラスなのであれば、DECLARE_DYNAMIC などを利用することでも型情報を持たせることができます(こちらは、RTTI とは別の仕組みなので、リークしません)。

     

    サンプルだけでは状況がつかめないため、判断しきれないのですが、何らかの理由でオブジェクトの型名の文字列が必要というのはそう多くはないのではと思いますが。

     

    2007年10月12日 2:34
  •  

    こんにちは。

     

    > if( typeid( hoge ) == typeid( CHoge ) ){
    >  // 同じ時の処理...

    > }

     

    比較するものがインスタンスが作成していなければならならいと思い込んでいました。

    なので文字列による比較が必要なものと思っていました。

    目的を書いていませんでしたが、ご指摘のようにクラスの判別です。

     

    上記の方法であればメモリリークの報告がデバッグウィンドウに出力されませんでした。

     

    非常に助かりました。ありがとうございました !

    2007年10月12日 5:44