説明しがたいエラーなのですが、、、

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
doss

説明しがたいエラーなのですが、、、

#1

投稿記事 by doss » 10年前

RPGのゲームをオブジェクト指向を利用して作成しようとしているのですが、
エラーが起きてしまいました、なぜだかわからないので質問したいと思います。

コード:

/* Battle.h */
#ifndef BATTLE_H
#define BATTLE_H

//#include "Box.h"
#include "Charctor.h"
//#include "Image.h"

class BATTLE{
private:
	//IMAGE BackGround;
	//BOX *box;
	CHARCTOR *charctor;
public:
	BATTLE();
	BATTLE(CHARCTOR*);//,BOX*,IMAGE);
	~BATTLE();
	void Draw();
};

#endif BATTLE_H

/* Battle.cpp */
#include "Battle.h"

BATTLE::BATTLE( CHARCTOR *charctor){// , BOX *box , IMAGE background){
	//ここの意味はない
	this->charctor = new CHARCTOR();//charctor;
	//this->box = box;
	//this->BackGround = background;

//	for(int i=0; i<4; i++)
//            this->charctor[i] = CHARCTOR::CHARCTOR();

		this->charctor[0] = CHARCTOR::CHARCTOR();
	        //ここで何故かエラー
                this->charctor[1] = CHARCTOR::CHARCTOR();
		this->charctor[2] = CHARCTOR::CHARCTOR();
		this->charctor[3] = CHARCTOR::CHARCTOR();

//	for(int i=4; i<10; i++)
//		this->charctor[i] = CHARCTOR::CHARCTOR();

//	for(int i=0; i<10; i++)
//		this->box[i] = BOX::BOX();

//	this->BackGround = IMAGE::IMAGE();
}
BATTLE::BATTLE(){}
BATTLE::~BATTLE(){}
void BATTLE::Draw(){}
for文のすべてがエラーなら納得できるのですが、その中の一つだけが
エラーになるのはなぜなのでしょうか。教えていただけると助かります。

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

Re: 説明しがたいエラーなのですが、、、

#2

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

本当に一つだけがエラーになるのですね?
doss さんが書きました:

コード:

        this->charctor[2] = CHARCTOR::CHARCTOR();
        this->charctor[3] = CHARCTOR::CHARCTOR();
この部分では、本当にエラーが起きないのですね?
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

初級者
記事: 200
登録日時: 13年前

Re: 説明しがたいエラーなのですが、、、

#3

投稿記事 by 初級者 » 10年前

「何を」したときに
「どんな」エラーが
出るのか、具体的に
書いてください。

doss

Re: 説明しがたいエラーなのですが、、、

#4

投稿記事 by doss » 10年前

みけCATさん

コード:

        this->charctor[2] = CHARCTOR::CHARCTOR();
        this->charctor[3] = CHARCTOR::CHARCTOR();
では、動作に問題ありません。

初心者さん
情報が足りなかったようで申し訳ないです。
「何を」
・このコードで実行したとき
「どんな」
・実行時に問題はないのですが、実行が終わった際に、
Critical error detected c0000374
Windows によって 実験.exe でブレークポイントが発生しました。

ヒープが壊れていることが原因として考えられます。.exe または読み込まれた DLL にバグがあります。

あるいは、.exe がフォーカスを持っているときに、ユーザーが F12 キーを押したことが原因として考えられます。
といったエラーが出てきてしまうのです。

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

Re: 説明しがたいエラーなのですが、、、

#5

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

doss さんが書きました:

コード:

	this->charctor = new CHARCTOR();//charctor;
ここで1要素しか確保していないのに、2要素目(1-origin)以降にアクセスしたら、その時の動作は保証されないと思います。
2番目、3番目(0-origin)にアクセスしてもエラーが出ないというのは不思議ですね。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
h2so5
副管理人
記事: 2212
登録日時: 13年前
住所: 東京
連絡を取る:

Re: 説明しがたいエラーなのですが、、、

#6

投稿記事 by h2so5 » 10年前

オフトピック
× Charctor
○ Character

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: 説明しがたいエラーなのですが、、、

#7

投稿記事 by softya(ソフト屋) » 10年前

newでの配列確保が正しくないので正しく動作する訳がないのですが、あたかもコンパイル時に文法エラーが出るかのように説明されているので回答者が当惑したと言う状況ですね。正確な説明であれば、もっとみなさん的確に答えられたと思います。
ポインタの扱いに不慣れであれば、STLのvectorなどを積極的に活用されてはどうでしょうか? 今のコードは非常に危なっかしいコードです。 CHARCTOR::CHARCTOR()で戻るインスタンスもどうなっているか不明なところですが。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

doss

Re: 説明しがたいエラーなのですが、、、

#8

投稿記事 by doss » 10年前

お騒がせしてしまったようで大変申し訳ないです。
softyaさんの言うように普通の配列に書き直したらしっかりと動作しました。
ポインタの使い方を一度おさらいしてきます。
ありがとうございました。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: 説明しがたいエラーなのですが、、、

#9

投稿記事 by softya(ソフト屋) » 10年前

既に書いた通り、コンストラクタ・デストラクタの動作を確認されたほうが良いですよ。
> CHARCTOR::CHARCTOR()で戻るインスタンスもどうなっているか不明なところですが。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

かずま

Re: 説明しがたいエラーなのですが、、、

#10

投稿記事 by かずま » 10年前

softya(ソフト屋) さんが書きました: newでの配列確保が正しくないので正しく動作する訳がないのですが、あたかもコンパイル時に文法エラーが出るかのように説明されているので回答者が当惑したと言う状況ですね。正確な説明であれば、もっとみなさん的確に答えられたと思います。
No.4 で、実行時エラーであることが明確に説明されています。
doss さんが書きました: softyaさんの言うように普通の配列に書き直したらしっかりと動作しました。
具体的にどのように書き直したのですか?
softyaさんは STLのvector を薦めていて、「普通の配列」ではありませんよね。
次のようにしたということですか?

コード:

this->charctor = new CHARCTOR[10];
みけCAT さんが書きました: ここで1要素しか確保していないのに、2要素目(1-origin)以降にアクセスしたら、その時の動作は保証されないと思います。
2番目、3番目(0-origin)にアクセスしてもエラーが出ないというのは不思議ですね。
これは興味深い問題です。
ヒープのメモリ管理の問題なので実装依存ですが、ちょっと調べてみました。

VC++ 2008 Express Edition では、メモリウィンドウが使えたのに、
VC++ 2010 Express Edition では、使えなくなったので、
次のようなプログラムを書いてみました。

コード:

#include <iostream> // cout, endl
#include <cstring>  // strcpy
#include <iomanip>  // setw

using namespace std;
 
class CHARCTOR {
public:
    char buf[32];
    CHARCTOR() { strcpy(buf, "abcdefghijklmnopqrstuvwxyz01234"); }
};

void dump(void *vp, size_t n)
{
    int *p = static_cast<int *>(vp);
    n /= sizeof(int);
    cout << hex << setfill('0');
    for (size_t i = 0; i < n; i++)
        cout << p + i << ": " << setw(8) << p[i] << endl;
}

int main()
{
    CHARCTOR *cp1 = new CHARCTOR;
    CHARCTOR *cp2 = new CHARCTOR;
    cout << "cp1 = " << cp1 << endl;
    cout << "cp2 = " << cp2 << endl;
    dump(cp1 - 1, sizeof(CHARCTOR) * 5);
}
実行結果を編集したもの

コード:

cp1 = 005F1290
cp2 = 005F12B8

005F1270: 005f1450
005F1274: 00000001
005F1278: 04d8a9a1
005F127C: 0800b210
005F1280: 00000000
005F1284: 005f1260

005F1288: 03d8a9a6  # cp1 の管理情報
005F128C: 0800b216  # cp1 の管理情報

005F1290: 64636261  # cp1
005F1294: 68676665
005F1298: 6c6b6a69
005F129C: 706f6e6d
005F12A0: 74737271
005F12A4: 78777675
005F12A8: 31307a79
005F12AC: 00343332

005F12B0: 03d8a9a6  # cp2 の管理情報
005F12B4: 0800b211  # cp2 の管理情報

005F12B8: 64636261  # cp2
005F12BC: 68676665
005F12C0: 6c6b6a69
005F12C4: 706f6e6d
005F12C8: 74737271
005F12CC: 78777675
005F12D0: 31307a79
005F12D4: 00343332

005F12D8: 05d8a9a0  # 未割当領域の管理情報
005F12DC: 0800b211
005F12E0: 0006a260
005F12E4: 00000001
005F12E8: 00000000
005F12EC: 00000000
005F12F0: 1bd9a9bf
005F12F4: 0000b217
005F12F8: 005f1748
005F12FC: 005f1418
005F1300: 00000000
005F1304: 00000000
005F1308: 00000000
005F130C: 00000000
new で確保された領域の直前の 8バイトはメモリの管理情報が入っています。
new で確保された領域の後は、未割当領域の管理情報が入っているようです。
this->charctor[1] = CHARCTOR::CHARCTOR(); ではこの管理情報を破壊してしまうので
No.4 の dossさんの説明の「実行が終わった際に、... ヒープが壊れていることが
原因として考えられます。」となるのだと思います。
this->charctor[2] = CHARCTOR::CHARCTOR();
this->charctor[3] = CHARCTOR::CHARCTOR();
これらは、単に未割当領域を無断で使っているだけで問題が発覚しないようです。

閉鎖

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