• ベストアンサー

【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 何卒よろしくお願いいたします。

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

  • ベストアンサー
  • momenlara
  • ベストアンサー率60% (6/10)
回答No.2

> deleteの所でエラーになります。 とのことですが、ソース中にはdeleteが2回出てきますね。 どちらのdeleteでエラーが出ているでしょうか? > (確保していない領域をdeleteしようとしたときのような) エラーの意味がよく分からないときには、エラーログをそのままコピーアンドペーストしてしまえば誤解がなくてよいかもしれません。 ここからは推測ですが、やはりObjectクラスの内部処理に問題がある気がします。 例えば、Objectクラス内に初期化されていない(使われていない)ポインタ変数があって、デストラクタ内でそれをdeleteしている、とかですね。 デバッガを使うとポインタ変数を宣言した時に、自動的に0に初期化してくれる場合がありますが、通常は明示的に初期化していない変数の値は不明で、なんらかの適当な値が入っている可能性があります。 この場合、質問にあるような動作になるかな、なんて思いました。

sirooni
質問者

お礼

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

sirooni
質問者

補足

ありがとうございます。 エラーは最初の方の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がおかしいということだけ分かりました。 デストラクタは定義していないので、やはり別の場所なのでしょうか・・・

その他の回答 (3)

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.4

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

sirooni
質問者

お礼

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

sirooni
質問者

補足

やはりそうなんでしょうか。 ずっとデバッグしてるんですが、少し変えるごとに別のnew、deleteでエラーが起こったり、何も起こらなかったりします。 デバッガで実行するとエラーが起こらない確率が上がりますがたまにエラーが起こります。 ただ、obj[0]->Run();ではエラーはいつも起こらず、それ以降に起こるのでやっぱりクラスの中身のどこかがおかしいとは思うのですが。

  • momenlara
  • ベストアンサー率60% (6/10)
回答No.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];

sirooni
質問者

お礼

何度もありがとうございます。 実際のプログラムでは、サンプルデータを作るオブジェクトがあって その結果をオブジェクトの引数にするのでこの方法以外思いつかないんです。 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)がエラーになりました。 やはりどこか別のところがおかしいみたいですね・・・

回答No.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; }

sirooni
質問者

お礼

ありがとうございます。 と言うことは問題は他の箇所ですね。

関連するQ&A

  • オブジェクトを配列として扱いたい

    Java(オブジェクト指向)を始めて数日の者です。 LinkedListを利用し、インスタンス化したオブジェクトをListに入れて 扱えるようにしたいと考えています。 具体的には LinkedList<クラス名> array = new LinkedList<クラス名>(); クラス名 object1 = new クラス名(); -object1の処理- array.add(object1); -object1の処理- array.add(object1); -object1の処理- array.add(object1); このようにして、object1を配列で管理するイメージです。 object1の処理結果は、毎度変わっています。 しかしこれですと、最後のobject1の処理の内容がすべてのarray(i)に入ってしまいます。 要は、array(i)は全て、同じobject1を参照しているだけ。 object1の変更結果がarray(i)に入っていくというイメージでは無い、ということでしょうか? また、この他でインスタンス化したものを配列で管理できるような方法がございましたら、ご教授いただけると幸いです。m(_ _)m 動的に配列の要素数を変更(要素が追加)ができるようにしたいのです。

    • ベストアンサー
    • Java
  • 3次元配列の動的確保

    2次元配列は、 // 動的確保 int **mat = new int*[row]; for(i = 0; i < row; i++) mat[i] = new int[col]; //解放 for(i = 0; i < row; i++) delete [] mat[i]; delete [] mat; で、生成と開放はできたのですが、3次元となると、途端にわからなくなります。 かれこれ1時間半は試行錯誤はしているのですが、たどり着きそうにありません。 どなたかご教授願います。

  • C++の初期化チェックに関する質問です

    C++のクラスの初期化済み、未初期化を調べる方法についてご質問させていただきます。 以下のプログラムを実行するとコメント部分//Aで実行時にエラーが発生すると思います。 class Object { int *arg ; public : Object( int len ) { arg = new int[ len ] ; } public : ~Object( ) { delete[ ] arg ; } } ; int main( ) { Object obj1 = Object( 100 ) ; Object *obj2 ; obj1 = *obj2 ; // A return 0 ; } エラー理由はobj2が初期化されていないからだと分かるのですが、 プログラマー側でobj2が初期化されているか調べる方法はあるのでしょうか? 定義時にObject *obj2 = NULL ;としてif文で回避する以外に方法が ありましたら、ぜひご教授願います。

  • C++でのクラスオブジェクトの破棄

    こんにちは。 C++では、プログラムの終了時に、全てのクラスオブジェクトは、デストラクタが呼び出されて破棄されますが、プログラムの途中で、クラスオブジェクトを明示的に破棄する方法はあるのでしょうか? 例えば、new演算子によってメモリを動的に割り当てたポインタなら、delete演算子で破棄できますが、 クラスオブジェクトにdelete演算子は使えないようです。 何かいい方法を知っておられる方がいらっしゃれば、是非アドバイスを頂きたいと思います。

  • 配列の中身のdelete

    こんにちは 配列を使った際、うまいことDeleteが働いてくれないため メモリが開放されずに困っています、 初歩的な質問で申し訳ありませんが、質問させて下さい。 下記のプログラムでは、 単純にメモリ確保とメモリ開放を行っていると思うのですが… 注釈にもあるように、Deleteでメモリが開放されません。 #include <iostream> using namespace std; class Base { }; class Sub : public Base { char size[256];//領域確保用 }; void main() { Base* obj[10000]; for(int cnt=0;cnt<10000;cnt++) { obj[cnt] = new Sub; } for(int cnt=0;cnt<10000;cnt++) { delete obj[cnt];//メモリが開放されない } } ポインタが怪しいと思うのですが、 どうにかうまいことメモリを開放することは出来ないでしょうか。 よろしければ返答お願いいたします。

  • C++のnewで確保した領域について

    こんにちわ。C++を勉強し始めた者です。 new演算子を使ってインスタンスを生成した場合、それはスタックではなくヒープ領域に確保され、不要になったらdeleteを使って領域を解放しなければいけない認識です。 C++の初心者向けサンプルコードを見ていて疑問があったので質問させてください。 (例)クラスA.cpp ======================== #include <Car> #include <Garage> ~略~ クラスAのコンストラクタ{ Car *mycar = new Car("プリウス"); addGarage( mycar ); } クラスAのデストラクタ{ } ======================== 上記のような実装のクラスAがあったのですが、コンストラクタでCarクラスのインスタンス生成をして、オート変数の*mycarに格納して、Garageの公開関数に渡しています。 質問1:このクラスAをインスタンス生成した場合、コンストラクタで確保したヒープ領域は、プログラム終了時まで解放されない認識であっていますか? 質問2:オート変数の*mycarはコンストラクタからreturnした時点で解放されてしまうので、今のままではデストラクタでヒープ領域をdeleteできない認識であっていますか? 質問3:newで生成したインスタンスへのポインタは、その関数内でdeleteしない場合、メンバ変数やstatic変数、グローバル変数に格納しなければdeleteできなくなるという理解であっていますか? 質問4:C++のコードでnewした戻り値をオート変数に格納するプログラムは通常使うことはあるのですか?

  • STLを使わずに可変長配列を再現する方法

    STLのlistが(配列に比べると)想像以上に遅かったので C++で可変長配列を再現したいのですけども 配列の拡張が思った以上に遅く困っています。 毎回newではオーバーヘッドが発生しますので、 現在は配列を一定数確保しておき 足りなくなったら配列を拡張(再確保)しています。 現在の配列のアドレスを一旦退避させてdeleteし、 新たにnewで生成して復帰させるといった感じです。 ただしこれでは、配列の要素数が増えるほど遅くなり、 オブジェクトの参照ならまだしも実体の場合は 全てコピーしなければならないので、 場合によってはSTLのlistよりも遅くなってしまいます。 newで生成してるのでできればreallocは使わずに 再現したいのですが、どうにか方法は無いでしょうか? よろしくおねがいします。 //----------------------------------------------- struct Test {   int val;   Test( int _val ){ val=_val; } }; Test obj1( 1 ); Test obj2( 2 ); Test obj3( 3 ); // 元のデータに代入 Test **ptr = new Test*[2]; ptr[0] = &obj1; ptr[1] = &obj2; // 退避させる Test **tmp = new Test*[2]; for( int i=0; i<2; i++ ) tmp[i] = ptr[i]; // 拡張する delete [] ptr; ptr = new Test*[4]; // 復帰させる for( int i=0; i<2; i++ ) ptr[i] = tmp[i]; delete [] tmp; ptr[2] = &obj3; //----------------------------------------------- ※NULLチェックなどはここでは省いています。

  • C++で領域の確保の方法

    今C++の勉強中なのですが、 領域の確保の方法でいい方法が知りたいのです。 ポインターのポインターを使って二次元配列の領域を確保したいのですがいい方法が思いつきません。 int **pBox; pBox = new int *[ 10 ]; for( int i=0; i<10; i++ ) { pBox[ i ] = new int[10]; } //ちなみに今はこんな感じのものしか考え付きませんint型[10][10] を確保したつもりです。 間違っていたら教えていただきたいです。 本題はこちらで、もっと効率のいい確保の方法を知りたいのでご協力を よろしくお願いします。

  • 多次元配列のメモリ解放

    多次元配列のメモリ解放についてです。 以下のような方法で多次元配列を確保した場合に、 --- char** ppMain; ppMain = new char*[3]; for (int i = 0; i < 3; i++){ ppMain[i] = new char[20]; } --- メモリ解放する場合、 --- for (int i = 0; i < 3; i++){ delete [] ppMain[i]; ppMain[i] = NULL; } delete [] ppMain; ppMain = NULL; --- で良いでしょうか? おそらく、new/deleteの回数が同じであれば問題ないと思うのですが。 少し混乱してしまって、 delete [] ppMain[i]; によって new char*[3]で確保したところも解放されており delete [] ppMain; が必要なく危険な領域まで解放しようとしているということはないでしょうか? ご専門、お詳しいかたコメント宜しくお願いします。

  • ActionScriptで配列をクリアする方法を教えてください。

    ActionScriptで、オブジェクトを格納した配列をクリアする正しい方法を教えてください。 具体的には、 ・new Array() で配列を生成する。 ・new Object() で生成したオブジェクトを配列に格納する。 ・配列の中身を処理したあと、配列を一度クリアする。 ・配列に別のオブジェクトを格納する。 ような処理をしたいのですが、メモリリークを起こさずに配列をクリアするにはどうしたらいいでしょうか? 例えば、イメージはこんな感じです。(意味のないコードですが) // 配列の生成 var arr = new Array(); // 配列にオブジェクトを格納 for (var i = 0; i < 5; i++) { var obj = new Object(); obj.num = i; } // 配列のクリア arr.length = 0; // クリアした配列に別のオブジェクトを格納 for (var i = 0; i < 5; i++) { var obj = new Object(); obj.num = i * 2; } 上記のコードで、arr.length = 0; で配列をクリアしていますが、これで配列に格納されたオブジェクトが確保したメモリがすべて解放されるでしょうか? あるいは、配列の内容がなくなるまで pop() 等で取り出す等の処理をする必要があるでしょうか? 以上よろしくお願いします。

    • ベストアンサー
    • Flash