• ベストアンサー

newの動作がおかしくなる?

CStringに似たデータ格納用のクラス(メンバ変数:newで確保したメモリ領域(int)、現在のデータ長(int)、データを格納した領域へのポインタ(char*))を作り、newで動的にメモリ領域を確保するようにしていたのですが、別々のところで使用したこのクラスのchar*の値が同じ0x980848という値になり、メモリ破壊が起きています。 他にもreturnの後に0x980848から始まる領域に0x980848という値そのものが勝手に格納されたり、newを実行するとSegmentation faultが発生したりもしています。 いずれの現象も限定的で、少しソースを変更するだけで起きなくなったりしますが、これが本当に現象が治まっているのか、単に使われるメモリの領域が変わっただけなのかはわかりません。 デバッグくらい自分でやれ!、という意見もあるかと思いますが何日もこの部分で行き詰まっているので助けてください。 要領を得ない質問だとは思いますが、このような現象が起こる原因に心当たりがある方、もしくはデバッグに関する指針のようなものでも結構ですので、何かありましたらご教授頂けないでしょうか。 よろしくお願いします。 環境はcygwin1.3.22上のgcc3.2、OSはWin98SEです。

質問者が選んだベストアンサー

  • ベストアンサー
  • jmh
  • ベストアンサー率23% (71/304)
回答No.2

コピーコンストラクタを書いても同じですか?

zaoldyeck
質問者

お礼

返事が遅れて申し訳ありません。 以下のようなコピーコンストラクタを定義することで、returnの辺りでコールされていたデストラクタが別々の値をdeleteするようになりました。 abcd(const abcd &a){ x = new char[10]; memcpy(x,a.x,10); } 余分に呼び出されていたデストラクタはコピーコンストラクタの一時オブジェクトの消滅時に呼ばれていたもののようです。 同様のソースをgcc/cygwinで試してみたところ、定義したのにもかかわらずコピーコンストラクタそのものが実行されていませんでした。 このため2重deleteがされていなかったようです。 何故実行されないのかは謎ですけど。 コンパイラが不要と判断したのでしょうか? 質問文のほうのソースはまだ試していませんが、return付近で2重にデストラクタが呼ばれるのは同じなので、これで解決できると思います。 ありがとうございました。

その他の回答 (1)

noname#6581
noname#6581
回答No.1

そういうわけのわからない現象が起きるときは、大抵メモリを壊しています。 (物理的にではなく、ソフト的に) 確保したメモリ領域をはみ出して書き込みをしているとか、二重freeをしているとかです。 プログラム全体を見直されたほうがいいと思います。

zaoldyeck
質問者

お礼

二重freeでもメモリ破壊は起きるのですね。 はみ出しての書きこみのほうは注視していたのですが、そちらにはあまり気を使っていませんでした。 改めて見てみるとデストラクタにdeleteを入れていたのが問題のようです。 それにreturnが組み合わさることで、二重delete、さらにメモリリークが発生していました。 ありがとうございました。 確認に使ったサンプルプログラムを載せておきます。 class abcd { public: char *x; abcd(void); ~abcd(void); }; abcd::abcd(void){ x = new char[10]; } abcd::~abcd(void){ delete[] x; } abcd test(void){ abcd a; return a; } main(){ abcd a; a = test(); }

zaoldyeck
質問者

補足

お礼に勘違いがあったので補足です。 実際に使っているクラスは'='をオーバーロードしていたので、メモリリークは発生していませんでした。 その代わり、returnの辺りで2回デストラクタが実行されてしまっているようです。 順番としてはreturnの直後にデストラクタが呼び出され、返り値が何かに代入されていればそちらを先に実行。その後もう一度デストラクタをコールするといった感じです。 以下のソースはgccでは問題ありませんでしたが、borland c++でコンパイルしたところその現象が現れました。 コンパイラは違いますが、問題としては同質のようなので載せておきます。 このような使い方はc/c++では無理なのでしょうか? class abcd { public: char *x; abcd(void){ x = new char[10]; } ~abcd(void){ delete[] x; } abcd &operator=(const abcd &a){ memcpy(x,a.x,10); return *this; } }; abcd test(void){ abcd hoge; return hoge; } main(){ abcd hoge2; hoge2 = test(); }

関連するQ&A