Detected memory leaks! が出ないようにしたい – プログラミング – Home

通知
すべてクリア

Detected memory leaks! が出ないようにしたい


谷岡
 谷岡
(@谷岡)
ゲスト
結合: 22年前
投稿: 33
Topic starter  

VC8.0 で MFC を使わない自作 DLL を作成しました。
その DLL をデバッグ版の MFC アプリケーションにリンクすると
アプリケーションの終了時に Detected memory leaks! が出てくる
ようになりました。

そのダンプ内容を見ると自作 DLL 内のクラスの静的メンバー変数 (std::string 型)
のメモリであることが分かりました。
静的メンバー変数なので最終的にはデストラクタが自動で呼ばれるはずです。

そこでもう少し調べてみると MFC の DLL の後処理で
_AFX_DEBUG_STATE::~_AFX_DEBUG_STATE() から _CrtDumpMemoryLeaks() が呼ばれ
そこで Detected memory leaks! が出ていることが分かりました。
そしてその後に自作の DLL の静的メンバー変数のデストラクタが呼ばれている
ことが分かりました。

デストラクタが呼ばれる前に _CrtDumpMemoryLeaks() が呼べれているので
メモリーリークと判断されてしまいました。
実際にはメモリーリークが起きていないのでメッセージを無視すればいいのですが
本当にメモリーリークが起きたときに気づきにくくなってしまいます。

この問題を解決する方法はないでしょうか?

試しにデバック版の自作 DLL に無理矢理 MFC をリンクしてみました。
そうすると自作 DLL が MFC に依存することになるので、自作 DLL の後処理
の後に MFC の後処理が実行され Detected memory leaks! は出なくなりました。
しかし必要のない MFC をリンクするのはもったいないので避けたいです。


引用解決済
トピックタグ
たいちう
 たいちう
(@たいちう)
ゲスト
結合: 23年前
投稿: 662
 

気にする必要はないと思いつつ私も気になる時があります。
次のような仕組みにして終了時に呼ぶのはいかがです?

class Hoge() {
static int *p;
public:
virtual ~Hoge() {
DeleteP();
}
static void DeleteP() {
delete p;
p = NULL;
}
};


返信引用
谷岡
 谷岡
(@谷岡)
ゲスト
結合: 22年前
投稿: 33
Topic starter  

たいちう様、アドバイスありがとうございます。

静的メンバ変数は以下のように std::string 型なので
std::string のデストラクタ以外は確保したメモリを解放
できないようになっています。
class Hoge {
static const std::string s;
};

MFC が _CrtDumpMemoryLeaks() ではなく
_CrtSetDbgFlag( _CRTDBG_LEAK_CHECK_DF ) を使っていれば
問題ないのですがわざわざ _CRTDBG_LEAK_CHECK_DF フラグを
消しているようです。


返信引用
YuO
 YuO
(@YuO)
ゲスト
結合: 22年前
投稿: 320
 

DLLが使うCRTは,DLLのものでないといけないのですか?
つまり,DLL内部のメモリを外部からfree/deleteしたり,その逆をしたり,のような処理
を必要としていますか?

必要としていないのであれば,デバッグ構成だけでもDLLが使うCRTを静的にリンクするも
のに変更してみてはどうでしょうか。


返信引用
たいちう
 たいちう
(@たいちう)
ゲスト
結合: 23年前
投稿: 662
 

> 静的メンバ変数は以下のように std::string 型なので
> std::string のデストラクタ以外は確保したメモリを解放
> できないようになっています。

この仕様をどこまで変更してよいかによりますが、
次のようなことはできませんか?
intがstringに変わっただけですよ。

class Hoge {
public:
static const std::string * s;
Hoge() {
delete s;
s = new std::string(ここで初期化するとか);
}
virtual ~Hoge() { deleteS(); }
static void deleteS() { delete s; s = NULL; }
};

const std::string * Hoge::s(new std::string(ここで初期化してもいい));


返信引用
谷岡
 谷岡
(@谷岡)
ゲスト
結合: 22年前
投稿: 33
Topic starter  

YuO 様

なるほどと思ったのですが残念ながら DLL のヘッダーが標準ライブラリの
クラスに依存しているためアプリケーションと DLL が違う CRT の場合、
誤動作する可能性があります。
そのため boost のようにライブラリのファイル名を CRT などで分けています。


返信引用
谷岡
 谷岡
(@谷岡)
ゲスト
結合: 22年前
投稿: 33
Topic starter  

たいちう様

変更箇所が多いこととユーザから見た新しい API の追加が必要なので
この方法はちょっと影響が大きいと思っています。
また、クラスに不変条件が成立しなくなるメソッドがあると扱いが
難しくなるような気がします。


返信引用

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました