newしたものをdeleteした時に失敗

[戻る]
じゃこ 2007/06/13(水) 04:32:36
いつもお世話になっております。
私、かなりのMFC初心者ですが、よろしくお願いします。

WinXP SP2
V6.0 MFC 使用です。

EXEのソース内でnewしたクラスを別のDLLの関数内でdeleteしています。
EXE側のプロジェクトでデバッグをしているとDLLの関数内のdeleteの箇所で勝手に
ブレイクポイントが立ち、"Invalid Address specified to RtlValidateHeap"の
メッセージがアウトプットに表示されます。

何故かこの現象が、DLLが「Win32 Release」でビルドしたDLL時のみ発生します。
リリース版でビルドした時のみ発生するので、今の所、製品版として問題無いの
ですが、デバッグで毎回ブレイクポイントが立つのと、たんに運良く動作している
気がしてなりません。

newで確保したアドレスと、delete時のアドレスが一致するのは確認しました。

MFC初心者の為、何故こういった事になるか理解に苦しんでいます。
よろしくお願いします。

・サンプルソース
 (量が多い為、実ソースでありませんが、こういった構成になっています)
(myClassは別DLLになっています)

VOID CMyExe::Main()
{
   CMyClass myClass;
   CMember *pMember = new CMember ();

   // メンバー追加
   myClass.Append (pMember);

   // メンバー削除
   myClass.Empty ();
}

VOID myClass::Append (CMember *pMember)
{
   m_pMember = pMember;
}

VOID myClass::Empty()
{
   delete m_pMember;   // ここでブレイクポイントが立ちます
}

Blue 2007/06/13(水) 07:05:37
単に、リンクしているlibやヘッダファイルに相違があるだけとか。

じゃこ 2007/06/13(水) 08:57:41
Blueさん、ありがとうございます。
そもそも何でdeleteの箇所で"Invalid Address specified to RtlValidateHeap"の
メッセージが出力されるのかが分からないんですよね。
debugモードでnewしたものをreleaseモードでdeleteしても問題無いと思うのですが・・・

Blue 2007/06/13(水) 09:20:47
DLL側のクラスのメンバ変数や仮想関数を増やしたりすると、
古いままのヘッダやlibを使っていると、確実にメモリ面で相違が出ます。
(たとえば、メンバ変数にint型の値を追加しただけで、他のメンバ変数の
参照位置がずれるとか。)

>debugモードでnewしたものをreleaseモードでdelete
そのようなつくりは出来ないと思いますけど。


ReleaseでNGでDebugでOKってことは、よくありうると思います。
(メモリの初期化等)
ReleaseとDebugの違いを調べてみてはどうでしょうか?

ITO 2007/06/13(水) 09:49:02
Debugは、特にメモリー操作の場合はNGにならないように動くことがあるみたいです。
僕も経験あるのですが、理由は良くわかりません。
debugモードのDUMP表示にメモリーリーク等、何かでていないですか?

ここのところが気になります。
>EXEのソース内でnewしたクラスを別のDLLの関数内でdeleteしています。
new - deleteは同じルーチンで行わないとまずいと思います。
普通は、EXE側でnewしたならEXE側の終了処理のところでdeleteします。
DLL側はあくまでもEXE側でnewしたクラスを参照・継承等で使用するだけにしたほうが
いいと思います。
逆に、DLL側でnew-deleteする方法もあると思いますが、EXE側との関連があるので
難しいと思います。

じゃこ 2007/06/13(水) 11:19:11
Blueさん、ITOさん、ありがとうございます。

Blueさん
ヘッダやLIBファイルは確認しました。問題無いハズなのですが・・・。

>そのようなつくりは出来ないと思いますけど。
言葉足らずですいません。
「debugモードのEXEでnewしたものをreleaseモードのDLLでdeleteした」でした。

ITOさん
>debugモードのDUMP表示にメモリーリーク等、何かでていないですか?
debugモード時は何も出てきません。
やはり、newとdeleteは同じEXEかDLLでしないといけないと言う事でしょうか?

Blue 2007/06/13(水) 11:31:14
>やはり、newとdeleteは同じEXEかDLLでしないといけないと言う事でしょうか?
そうすべきでしょう。

参考)
http://forums.microsoft.com/MSDN-JA/ShowPost.aspx?PostID=1702483&SiteID=7

ITO 2007/06/13(水) 13:49:03
>やはり、newとdeleteは同じEXEかDLLでしないといけないと言う事でしょうか?
buleさんの意見にあるとおりに、そうすべきだと思います。
たとえ、
 buleさんの紹介されたサイトより、
「LocalAlloc/GlobalAlloc や CoTaskMemAlook などの APIベースの
  メモリ確保を行う必要があります。
メモリの開放は、LocalFree/GlobalFree や CoTaskMemFree などを
用いる必要があります。」
に変更したとしても、
1. DLLが勝手に開放してしまったクラスををEXEで使ってしまう。
2. 未だEXEで確保していないクラスをDLLで使用してしまう。
この2項目が完全にないということならばまだいけるかも知れませんが
かなり難しいと思います。

じゃこ 2007/06/13(水) 16:39:56
[[解決]]
BLUEさんのMSDNへのリンク、大変為になりました。
ありがとうございます。

BLUEさんとITOさんが言われるとおり、同じDLL内で処理したいと思います。
既に出来上がってるシステムなので、猛烈に大変ですが・・・(^_^;)

ありがとうございました。大変勉強になりました。
私一人ではとても解決出来なかったと思います。

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