いつもお世話になっております。
私、かなりの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; // ここでブレイクポイントが立ちます
}
単に、リンクしているlibやヘッダファイルに相違があるだけとか。
Blueさん、ありがとうございます。
そもそも何でdeleteの箇所でInvalid Address specified to RtlValidateHeapの
メッセージが出力されるのかが分からないんですよね。
debugモードでnewしたものをreleaseモードでdeleteしても問題無いと思うのですが・・・
DLL側のクラスのメンバ変数や仮想関数を増やしたりすると、
古いままのヘッダやlibを使っていると、確実にメモリ面で相違が出ます。
(たとえば、メンバ変数にint型の値を追加しただけで、他のメンバ変数の
参照位置がずれるとか。)
>debugモードでnewしたものをreleaseモードでdelete
そのようなつくりは出来ないと思いますけど。
ReleaseでNGでDebugでOKってことは、よくありうると思います。
(メモリの初期化等)
ReleaseとDebugの違いを調べてみてはどうでしょうか?
Debugは、特にメモリー操作の場合はNGにならないように動くことがあるみたいです。
僕も経験あるのですが、理由は良くわかりません。
debugモードのDUMP表示にメモリーリーク等、何かでていないですか?
ここのところが気になります。
>EXEのソース内でnewしたクラスを別のDLLの関数内でdeleteしています。
new - deleteは同じルーチンで行わないとまずいと思います。
普通は、EXE側でnewしたならEXE側の終了処理のところでdeleteします。
DLL側はあくまでもEXE側でnewしたクラスを参照・継承等で使用するだけにしたほうが
いいと思います。
逆に、DLL側でnew-deleteする方法もあると思いますが、EXE側との関連があるので
難しいと思います。
Blueさん、ITOさん、ありがとうございます。
Blueさん
ヘッダやLIBファイルは確認しました。問題無いハズなのですが・・・。
>そのようなつくりは出来ないと思いますけど。
言葉足らずですいません。
「debugモードのEXEでnewしたものをreleaseモードのDLLでdeleteした」でした。
ITOさん
>debugモードのDUMP表示にメモリーリーク等、何かでていないですか?
debugモード時は何も出てきません。
やはり、newとdeleteは同じEXEかDLLでしないといけないと言う事でしょうか?
>やはり、newとdeleteは同じEXEかDLLでしないといけないと言う事でしょうか?
そうすべきでしょう。
参考)
http://forums.microsoft.com/MSDN-JA/ShowPost.aspx?PostID=1702483&SiteID=7
>やはり、newとdeleteは同じEXEかDLLでしないといけないと言う事でしょうか?
buleさんの意見にあるとおりに、そうすべきだと思います。
たとえ、
buleさんの紹介されたサイトより、
「LocalAlloc/GlobalAlloc や CoTaskMemAlook などの APIベースの
メモリ確保を行う必要があります。
メモリの開放は、LocalFree/GlobalFree や CoTaskMemFree などを
用いる必要があります。」
に変更したとしても、
1. DLLが勝手に開放してしまったクラスををEXEで使ってしまう。
2. 未だEXEで確保していないクラスをDLLで使用してしまう。
この2項目が完全にないということならばまだいけるかも知れませんが
かなり難しいと思います。
BLUEさんのMSDNへのリンク、大変為になりました。
ありがとうございます。
BLUEさんとITOさんが言われるとおり、同じDLL内で処理したいと思います。
既に出来上がってるシステムなので、猛烈に大変ですが・・・(^_^;)
ありがとうございました。大変勉強になりました。
私一人ではとても解決出来なかったと思います。