vectorのイテレータ処理で失敗する

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
dic
記事: 658
登録日時: 14年前
住所: 宮崎県
連絡を取る:

vectorのイテレータ処理で失敗する

#1

投稿記事 by dic » 11年前

よくわからないエラーがでます。
クラス CEnemy をvectorでラップして、使っているのですが、
前までは動いていたのですが、いろいろプログラムを追加していっていると
動いていた部分が動かなくなりました。
下がそのソースコードで、エラーのダイアロボックスも上げておきます。

iterator がなにやらエラーの原因のようなのですが、
何が原因か、さっぱりわかりません。
下のソースコードの7行目でエラーになります。

どういったことが原因なのでしょうか?

コード:


//	=========================================================================
void	Cステージ::敵リストの処理()
{
	vector<CEnemy>::iterator p = g_tInfo.mv_Enemy.begin();

	while( p != g_tInfo.mv_Enemy.end() )
	{
		if( m_frame == p->m_add )
			p->m_state = 1;
		if( -1 == p->m_add )
			p->m_state = 1;
		p++;
	}
}
添付ファイル
WS000004.jpg
エラーのダイアログボックス
WS000004.jpg (37.29 KiB) 閲覧数: 6868 回

YuO
記事: 947
登録日時: 14年前
住所: 東京都世田谷区

Re: vectorのイテレータ処理で失敗する

#2

投稿記事 by YuO » 11年前

エラーの該当行周辺を見ると,

コード:

	void _Compat(const _Myiter& _Right) const
		{	// test for compatible iterator pair
		if (this->_Getcont() == 0
			|| this->_Getcont() != _Right._Getcont())
			{	// report error
			_DEBUG_ERROR("vector iterators incompatible");
というコードになっています。
そして,<vector>と<xutility>を行き来しながらコードを読み解くと,_Getcont()はその名の通り,反復子が所属するコンテナオブジェクトへのポインタを返す内部関数のようです。
で,上記のコードは,異なるコンテナに所属するか,コンテナに所属しない反復子を使って比較をしようとした結果,_DEBUG_ERRORとなったのだと推測されます。

イテレータのループ中に,mv_Enemy自体が別のオブジェクトになっていませんか。
本当にm_stateの変更以外にmv_Enemy自体が置き換わるような処理を行っているのではないでしょうか。

dic
記事: 658
登録日時: 14年前
住所: 宮崎県
連絡を取る:

Re: vectorのイテレータ処理で失敗する

#3

投稿記事 by dic » 11年前

>>YuOさん
回答ありがとうございます。

なぜかエラーになってしまう箇所を思い出しました。

まず、

コード:


typedef	struct
{
	int		m_mode;

	int		m_slot_number;	//	使用しているスロットの番号 1~3

	C機体	m_機体;		//	プレイヤーの情報
	C機体	m_機体2;		//	プレイヤーの情報
	C武器情報	m_武器[3];
	C武器情報	m_武器2[3];
	int		m_Image爆発[16];
	vector<C爆発>	mv_爆発;
	int		m_image敵[256];
	int		m_input[256];
	int		m_joystick1[0x0000FFFF];

	int		m_stage_clear[ステージ数];	//	ステージクリアフラグ
	int		m_攻略ステージ数;	//	1~
	C修理部隊		m_修理部隊;	//	修理部隊の情報

	vector<CEnemy>		mv_Enemy;
	vector<CBullet3D>	mv_EnemyBullet;
	vector<CBullet3D>	mv_PlayerBullet;
	int		m_enemyIndex;
	ボス	m_boss;
	int		m_所持金;
} _tInfo;

と宣言して

コード:

EXTN	_tInfo	g_tInfo;				//	メインで使用する変数
//EXTN は extern のマクロです。
と、実態を宣言しています。

この状態で初期化処理に

コード:

	memset( &g_tInfo, 0, sizeof(g_tInfo) );
を使用すると、この不可思議なバグが発生します。
今回は CEnemy クラスだけを書き込みましたが、
vector<CBullet3D> mv_EnemyBullet;
vector<CBullet3D> mv_PlayerBullet;
も、同じようなバグが発生します。(エラーの内容も同じです)

なので、memset( ... をコメントアウトすると、うまく動きます。

ということは、vector<...> を含む変数がある場合
memset( &g_tInfo, 0, sizoef(g_tInfo) );
はまずいという答えがでたのですが、これが原因でしょうか?

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: vectorのイテレータ処理で失敗する

#4

投稿記事 by みけCAT » 11年前

dic さんが書きました:ということは、vector<...> を含む変数がある場合
memset( &g_tInfo, 0, sizoef(g_tInfo) );
はまずいという答えがでたのですが、これが原因でしょうか?
たしかにvectorをmemsetするのはやばそうですね。
原因かどうかは、memsetを使わない初期化処理を組んで試すなどして自分で確認してみたらどうですか?
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
へにっくす
記事: 634
登録日時: 13年前
住所: 東京都

Re: vectorのイテレータ処理で失敗する

#5

投稿記事 by へにっくす » 11年前

dic さんが書きました:ということは、vector<...> を含む変数がある場合
memset( &g_tInfo, 0, sizoef(g_tInfo) );
はまずいという答えがでたのですが、これが原因でしょうか?
原因かどうかは不明ですが、少なくともクラス変数を含む構造体にmemsetは駄目だと思います。
少なくとも私はやりません。
classと同様、structにもコンストラクタを定義できるので、そちらで初期化してください。

memsetを使うとしたらC言語完全互換で、しかもポインタを含まない構造体と、配列だけです。

[迷信] とりあえず memset で初期化
C++における構造体の初期化
written by へにっくす

dic
記事: 658
登録日時: 14年前
住所: 宮崎県
連絡を取る:

Re: vectorのイテレータ処理で失敗する

#6

投稿記事 by dic » 11年前

>>へにっくすさん
>>みけCATさん
なるほど、memsetはまずいんですね。
う~ん、一発で初期化できないのか・・・
やっぱり力技ですな

解決しました。

YuO
記事: 947
登録日時: 14年前
住所: 東京都世田谷区

Re: vectorのイテレータ処理で失敗する

#7

投稿記事 by YuO » 11年前

dic さんが書きました:う~ん、一発で初期化できないのか・・・
やっぱり力技ですな
ではなくて……。
初期化構文でちゃんと初期化しましょう。

C++でクラスの初期化は基本的にはコンストラクタですが,配列全ての値を0にするのが初期化であるならば,VC++ 2010でも

コード:

struct tInfo // C++で無名構造体作ってtypedef名つける意味がない,Cでも無名構造体にする意味はない (Cではtypedef名とタグ名は別の名前空間)
{
    /* 省略 */
    int     m_input[256];
    /* 省略 */
    tInfo () : /* 省略, 定義順にするのが安全 */, m_input(), /* 省略 */ { }
};
のように()をつければ0になります。

また,コンストラクタを使わずに単純に,

コード:

tInfo ti = { };
でも,static時と同程度の値設定はできます。
オフトピック
memsetだの0埋めだのが初期化とは限らないので,これを単純に初期化とは書かないでおきます。
初期値として相応しい値を,初期化構文を使って設定すること以外のために「初期化」という言葉を使うと,本来の初期化に説明が必要になってしまうので。

ISLe()

Re: vectorのイテレータ処理で失敗する

#8

投稿記事 by ISLe() » 11年前

へにっくすさんがリンクした先の記事にも書いてありますが、memsetを使って内部表現0で埋めても、値として0になるとは限らないのですから、memsetを使うほうが力業と認識すべきです。

dic
記事: 658
登録日時: 14年前
住所: 宮崎県
連絡を取る:

Re: vectorのイテレータ処理で失敗する

#9

投稿記事 by dic » 11年前

>>ISLeさん
はい、そうですね。日本語って難しい

>>YuOさん
初期化構文ですね、そうします。

閉鎖

“C言語何でも質問掲示板” へ戻る