配列オブジェクトのデリート

アバター
せんちゃ
記事: 50
登録日時: 15年前
住所: 江別市東野幌町
連絡を取る:

配列オブジェクトのデリート

投稿記事 by せんちゃ » 14年前

今日1時間ほど悩まされたバグ(というか僕の勉強不足?)

僕の今書いているシューティングプログラムは動的にメモリを確保することをコンセプトに書いています。
例えば自機のショットであれば

CODE:

class CHARACTER_SHOT{
private:
	int       BULLET_MAX;
	BULLET_BASS*  bullet;
	double   x;
	double   y;
	double   r;
	double ang;
	double bass_ang;

	double spd;
	double ExRate;

	int    knd;
	int    col;
public:
という感じでBULLET_BASSオブジェクトを持つクラスを作り

CODE:

//------------------------------------
//BULLET_MAX個の弾を作ります
//------------------------------------
/**/ CH_SHOT::CH_SHOT( int BULLET_MAX , double x , double y , double r , double ang , 
			 double spd , int knd , int col , double ExRate )
{
	this->BULLET_MAX = BULLET_MAX;
	bullet = new BULLET_BASS[BULLET_MAX];
	//----------------------------------------------------------
	//弾の当たり範囲、角度、速度、種類、色などはここで定義
	//----------------------------------------------------------
	this->r        =   r;
	this->ang      = ang;
	this->bass_ang = ang;
	this->spd = spd;
	this->knd = knd;
	this->col = col;
	this->ExRate = ExRate;
}

といった感じで外から値を入れた分だけの弾を生成する予定だったのですが…

デリートで躓きました、


キャラクターショットクラスのデストラクタで

CODE:

/**/ CH_SHOT::~CH_SHOT( void ){
	delete[] bullet;
	bullet = NULL;
}
とするとエラーが出ます。
僕がやりたかったのはキャラクターショットオブジェクトのデストラクタを呼ぶと同時に
弾オブジェクトのデストラクタも呼ぶということだったのですがどうも上手くいかない。


キャラクターオブジェクトのデストラクタを呼ぶ前に
ch_shot->DeleteObject();
というような関数を作ってこの中で弾オブジェクトだけを破棄します。

これで弾オブジェクトを破棄した後にキャラクターショットオブジェクトを破棄する、
としますとエラーは不思議となくなりました。



呼び出す順番に問題があったのだろうか??
と思いながらも、これも一つの学習だと思いつつ

これからはこの辺に気をつけてみましょう

ISLe
記事: 2650
登録日時: 15年前

RE: 配列オブジェクトのデリート

投稿記事 by ISLe » 14年前

デストラクタの中でメンバのデストラクタを呼ぶのはふつうにやってることですけど。

どんなエラーが出てるのか分からないですけど、よくあるのは他でポインタを覚えてて解放したオブジェクトをアクセスしてしまってるとか、単純にメモリの領域外に書き込んでいるとか。
あと確保していないのに解放してるとか。

問題を先送りするとあとから原因不明のエラーでもっと時間を無駄に費やすことになるかもしれませんよ。
最後に編集したユーザー ISLe on 2011年3月02日(水) 03:01 [ 編集 1 回目 ]

アバター
せんちゃ
記事: 50
登録日時: 15年前
住所: 江別市東野幌町
連絡を取る:

RE: 配列オブジェクトのデリート

投稿記事 by せんちゃ » 14年前

ISLeさん
いつもコメントありがとうございます!
日記を更新してからいろいろともう一回調べなおしてみたのですが、
配列オブジェクトのコンストラクタの呼び方に問題があったみたいです。

おそらく

CODE:

ch_shot    = new CH_SHOT[2]; //オブジェクトを配列で生成

//コンストラクタ呼び出し
ch_shot[0] = CH_SHOT( 20 ,   0 ,  0 , 10 , get_angle(  0 ) , 45 ,  0 , 0 , 1.5f );
ch_shot[1] = CH_SHOT( 20 ,   0 ,  0 , 10 , get_angle(  0 ) , 45 ,  0 , 0 , 1.5f );
というようなコンストラクタの呼び方に問題があったようです。
これだとちゃんとメモリを確保していなかったのかもしれません。

これを初期化する関数を作り、そこで同じことをやったらエラーは起きなかったので
これが原因の可能性が高いです(汗

ISLe
記事: 2650
登録日時: 15年前

RE: 配列オブジェクトのデリート

投稿記事 by ISLe » 14年前

CH_SHOT( 20 , 0 , 0 , 10 , get_angle( 0 ) , 45 , 0 , 0 , 1.5f );
で一時オブジェクトが作られます。
ch_shot[0]に一時オブジェクトが単純コピー(メモリ内容そのままコピー:シャローコピー)されます。
一時オブジェクトはこのあと適当なタイミングで解体されます。
つまりbulletメンバが持っているメモリ領域は一時オブジェクトに解体されて無効になってしまってます。

ゲームのプログラムなら、CH_SHOTに初期化用のメンバ関数を用意するのが良いでしょうね。
いちおう一時オブシェクトとかコピーコンストラクタとか代入演算子のオーバーロードとか検索して調べてみてください。
最後に編集したユーザー ISLe on 2011年3月02日(水) 17:33 [ 編集 1 回目 ]