• 締切済み

VisualC++6.0でdeleteがおかしい

今頃ですが、VisualC++6.0を使っています。とりあえずはこれで十分なので。で、WindowXPです。 1つのMFCAppWizardメインプロジェクトに対して、3つのライブラリ専用のサブプロジェクトを統合してプログラムを作っていますが、下記の簡単なdeleteもなぜか、出来なくなりました。 long* p; p = new long; delete p; 実行するとdelete pのところで、 NTDLL! 7c9668ad() PRONAME! free + 45 bytes PRONAME! operator delete(void *) + 9 bytes PRONAMEDlg::OnBtnCapturepicture() line 267 + 15 bytes のようなエラーが出てきます(デバッグモード)。 ちょっと気になったのが、最近、VirusBusterをインストールしましたので、実行後に、 'C:\Program Files\Trend Micro\Virus Buster 2007\TMAS_OE\TMAS_OEHook.dll' をロードしました、合致するシンボル情報は見つかりませんでした。 などというコメントが出てくるようになりました。 しかし、ちなみに全く新しいMFCAppWizardテストプロジェクトを作って、他のプロジェクトとリンク等、いっさいせずに簡単なもので動かすと、上記のコード、全く問題なく動きます。 この delete のエラーって、何が原因なのでしょうか。 考えられることがおわかりであれば、教えてください。

みんなの回答

回答No.5

メインプロジェクトとサブプロジェクトの間で必要としているdllが違っていたりしませんか? 例えばどちらかはDebugビルドなのにどちらかはReleaseビルドだとか、 片方はシングルスレッド用なのに片方はマルチスレッド用だとか……

chachakabu
質問者

お礼

わたしもこの辺を疑っています。 デバッグとリリースモードを混在していることはありませんが、リンクしているライブラリがシングルスレッドとマルチスレッド用が混在していたり、、、というのは、もう一度調べてみないといけないかもしれません。 この辺がほんと、めんどくさいというかわからないところです。結構いろいろとライブラリを使用しているので。 混合してはいけないこととして、 ○デバッグモードとリリースモード ○マルチスレッドとシングルスレッドのライブラリ ○ダイナミック用ライブラリとスタティック用ライブラリ ほんとめんどくさいですよねえ。 こんなの自動選択とかしてよって。 わたしもとりあえず思いつくのはこれですが、ほかにはなかったかな。 やはり、リンクしているライブラリの相性では、というのが、今のわたしの最大の疑問点です。 ありがとうございました。

  • guccii
  • ベストアンサー率31% (14/44)
回答No.4

なるほどぉ。困りましたねぇ。 同じようにプロジェクトを作成してみて思ったのですが、デバッグ版の場合、(確保したメモリのリストを管理しているので)参照しているヒープが違ったり、アドレスが多少ずれていたりした場合には、ASSERTする筈なんですよ。 で、今回はfree()の中でいきなり落ちてる... しかもこんな単純なコードで...。 断言することは尚早ですが、ライブラリのどこかでヒープを破壊している可能性が高いと思われます。確保したメモリ領域を超えてコピーしたり、ポインタ操作を誤って考えている以上の領域を使用したりしていないか見直した方が早いかもしれません。 確保しているヒープメモリに尖兵をつけて、破壊されていないかチェックするメモリ検査ロジックを追加するか、PURIFYみたいなメモリチェックをしてくれるソフトウエアを使って、メモリ不正がないか1度確認されたほうがよいのではないかと思われます。 くれぐれも断言はできませんが...

chachakabu
質問者

お礼

お返事ありがとうございました。 んーーん、やっぱり、これはちょっとかなり気合入れていろいろ調べていかないと、ちょっと一筋縄ではいきそうもありませんね。 VisualC++を使っていていつも思うのですが、複数のプロジェクトをリンクして使用する場合、それぞれのプロジェクトをコンパイルする際にどのライブラリをリンクしたかで、よくトラブルことがあります。今回の場合、サブプロジェクトにMFC系のライブラリ系をリンクして(共有MFCを使用するを選択するという意味)、メインでもMFC系のライブラリをリンクすると2重リンクでリンクエラーで落ちたり、スタティック系のライブラリかダイナミック系のライブラリかで、いちいち全部、チェックしてどのライブラリをリンクするかしないか、判断しないといけないので、やたらとめんどくさいです。スタンダード系のライブラリもメインとサブと両方デフォルトのままコンパイルすると、双方に入ってしまって、2重リンクになってしまったり。この辺が問題なのかなとも思っています。以前、マックのSymantecC++をしていましたが、こちらはほんとになんとも非常に使いやすかったですよ。それに比べて、VisualC++はなんともほんとに使いにくいです。 VisualC++も個々のプロジェクトをコンパイルするときはMFCやスタンダードライブラリを一緒にリンクすることをやめて、最後、全体をリンクするときに全部まとめてリンクすればいいのにね。ほんと、めちゃくちゃやっかいです。 んーーん、根性入れて、徹底的に調べるかな、、、どうしよう。。。

  • guccii
  • ベストアンサー率31% (14/44)
回答No.3

>long* p; >p = new long; >delete p; は、この通りのコードでしょうか?DLLで確保したメモリをEXEの中でdeleteしていたりしていないでしょうか? もしそうであれば、そのDLLの中にメモリを解放する関数を作って、EXEはそれを呼び出すようにしてください。 そうでない(上記の通りのコードで問題がでている)のなら、ちょっと厄介ですね。やってみてみないとなんともいえません。

chachakabu
質問者

お礼

コードは、まったくこのとおり、連続してこの順番なのですよ。 テスト用に全くこのとおりに挿入してみました。もともとは、クラスを作成して、それを new して使用したあと、delete しようとしたら出来なくて、調べているうちに、たった3行の簡単なコード long* p; p = new long; delete p; も出来ないことが判明しました。 うーーん、、、困った。 ちなみにこのテストコードは3つのサブプロジェクトではなく、メインプロジェクトの方に入れています。

  • guccii
  • ベストアンサー率31% (14/44)
回答No.2

不正なアドレスでdeleteしているものと思われます。 2重フリーしていない、該当ポインタにアドレス操作をしていないで、かつ、他の部分でメモリを壊していないとすると、考えられるパターンとしては、 1.EXEとDLLがそれぞれ別のランタイムとなっている。つまり、別のヒープから取得したメモリを別のヒープからdeleteしようとしている。EXEとDLLがそれぞれCのランタイムをスタティックにリンクしていませんか? 2.リリース版で取得したメモリをデバッグ版で解放しようとしている。MFCでデバッグ版の場合には、特別なnewが使用されて、デバッグ情報+確保したメモリ分のメモリが取得されます。newから実際に帰ってくるアドレスは、確保したメモリの先頭アドレスですが、deleteする際には、その前にデバッグ情報が存在していることを想定して動作します。このため、リリース版でアロケートしたメモリをデバッグ版でフリーしようとすると不正アドレスのフリーとなってしまいます。 というところではないでしょうか? "VirusBuster"と一緒に使用したことはないのではっきりとはわかりませんが、単にメモリ不正アクセス検査か何かのフックが呼ばれるようになっているのだと思います。今回の問題との直接的な関連については懐疑的です。

chachakabu
質問者

お礼

今、わたしが疑っているのは、リンクの仕方です。 メインは、MFCAppWizard(exe)ですが、他の3つは、Win32 Static Libraryで作っていて、MFCサポートありにしています。 それで、メインからコンパイルする際に、”設定”のところで、3つのサブプロジェクトはMFCを使用しないにしていて、メインAppは共有DLLでMFCを使用するにしています。すべてデバッグモードです。 また、オプションには /nodefaultlib:"nafxcwd.lib" /nodefaultlib:"msvcrtd.lib" /nodefaultlib:"libcd.lib" を設定しています。 これらの設定しないとリンクエラーになります。 この辺があやしいのでしょうか。

  • Interest
  • ベストアンサー率31% (207/659)
回答No.1

new したときにメモリが確保できていないとか? 確保できていないのに delete すると、プログラムが落ちますよね。 Visual C++ではnew演算子の動作が失敗したときにデフォルトでNULLを返しますが、現在の標準C++ではデフォルトで例外を生成するんだそうです。 ためしに、 long* p; p = new long; if(!p){ cout << "メモリ割り当てエラー\n"; return 1; } delete p; としてメモリが確保できているかどうか確認してみてはいかがでしょうか。

chachakabu
質問者

お礼

残念ながら p には値が設定されていたし、 *p = 10; とかを入れてみても、ちゃんと値が入っていました。