こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

【C++】オブジェクト配列の動的確保

Objectがクラスとして、以下のようなプログラムを書きました


Object **obj;
obj = new Object*[100];
for(i=0;i<100;i++){
    obj[i] = new Object(a,b,c);
    obj[i]->Run();
    delete obj[i];
}
delete [] obj;


するとdeleteの所でエラーになります。
(確保していない領域をdeleteしようとしたときのような)
何か間違っているのでしょうか。
何故かデバッガでは通ってしまいます。

環境:XP、VisualStudio2005

何卒よろしくお願いいたします。

投稿日時 - 2009-01-09 06:15:39

QNo.4615614

困ってます

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

> deleteの所でエラーになります。

とのことですが、ソース中にはdeleteが2回出てきますね。
どちらのdeleteでエラーが出ているでしょうか?

> (確保していない領域をdeleteしようとしたときのような)

エラーの意味がよく分からないときには、エラーログをそのままコピーアンドペーストしてしまえば誤解がなくてよいかもしれません。

ここからは推測ですが、やはりObjectクラスの内部処理に問題がある気がします。
例えば、Objectクラス内に初期化されていない(使われていない)ポインタ変数があって、デストラクタ内でそれをdeleteしている、とかですね。

デバッガを使うとポインタ変数を宣言した時に、自動的に0に初期化してくれる場合がありますが、通常は明示的に初期化していない変数の値は不明で、なんらかの適当な値が入っている可能性があります。
この場合、質問にあるような動作になるかな、なんて思いました。

投稿日時 - 2009-01-09 16:01:46

補足

ありがとうございます。

エラーは最初の方のdeleteの、一回目もしくは二回目に起きます。

Microsoft Visual C++ Debug Library
Debug Assertion Failed!
Program:...
File: dbgheap.c
Line: 1252
Expression: _CrtIsValidHeapPointer(pUserData)
For information on how your program can cause an assertion
failure, see the Visual C++ documentation on asserts.
(Press Retry to debug the applivation)

このエラー文が出るのですが、調べてみてdeleteがおかしいということだけ分かりました。
デストラクタは定義していないので、やはり別の場所なのでしょうか・・・

投稿日時 - 2009-01-09 18:26:00

お礼

オブジェクトのアドレスが変わっていないか調べましたが変わっていませんでした。
デストラクタを定義してみたところ、デストラクタが終了した後にエラーになりました。

投稿日時 - 2009-01-09 20:35:52

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(4)

ANo.4

クラス Object がおかしいとしか言いようがない気がする, って既に #1, #2 で指摘されてますね.

投稿日時 - 2009-01-10 18:29:49

補足

やはりそうなんでしょうか。
ずっとデバッグしてるんですが、少し変えるごとに別のnew、deleteでエラーが起こったり、何も起こらなかったりします。
デバッガで実行するとエラーが起こらない確率が上がりますがたまにエラーが起こります。

ただ、obj[0]->Run();ではエラーはいつも起こらず、それ以降に起こるのでやっぱりクラスの中身のどこかがおかしいとは思うのですが。

投稿日時 - 2009-01-11 02:20:41

お礼

すみません。
deleteを全て消したら通りました。
もう一度基礎から見直したいと思います。
お騒がせいたしました。

投稿日時 - 2009-01-12 23:05:53

ANo.3

これは、、なかなかやっかいですね。
残念ながらすぐには回答できなそうです。

ただ、今回の例に限っていえば、Objectポインタの配列は必要ないのでは?

for(i=0;i<100;i++){
    Object* obj = new Object(a,b,c);
    obj->Run();
    delete obj;
}

サンプルコードっぽいので、実際にはどうなのか分からないのですが、
すぐにdeleteしてしまうのであれば、ポインタをわざわざ配列に入れる必要はないように思います。
まあ、逃げと言えば逃げですが。(笑)

あと、「オブジェクト配列の動的確保」と言った場合に、
わたしが想像したのは以下のようなものでした。

Object* obj = new Object[100];

投稿日時 - 2009-01-09 21:17:32

お礼

何度もありがとうございます。

実際のプログラムでは、サンプルデータを作るオブジェクトがあって
その結果をオブジェクトの引数にするのでこの方法以外思いつかないんです。


deleteを変えて

Object **obj;
obj = new Object*[100];
for(i=0;i<100;i++){
    obj[i] = new Object(a,b,c);
    obj[i]->Run();
}
for(i=0;i<100;i++){
    delete obj[i];
}
delete [] obj;

としてみたところ、obj->Run()の中のnewでoutput.c(output.c - printf style output to a FILE)がエラーになりました。

やはりどこか別のところがおかしいみたいですね・・・

投稿日時 - 2009-01-09 23:08:55

ANo.1

それだけのコードでは問題がないようですが、
載せていない部分に重要な記述がないでしょうか?

class Object
{
public:
  Object(int, int, int) {}
  void Run() {}
};

int main()
{
  int i, a, b, c;
  a = b = c = 0;

  Object **obj;
  obj = new Object*[100];
  for(i=0;i<100;i++){
    obj[i] = new Object(a,b,c);
    obj[i]->Run();
    delete obj[i];
  }
  delete [] obj;
}

投稿日時 - 2009-01-09 09:05:16

お礼

ありがとうございます。

と言うことは問題は他の箇所ですね。

投稿日時 - 2009-01-09 18:25:52

あなたにオススメの質問