マップ表示プログラムのデバック中に例外がスローされた。

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
アバター
keito94
記事: 264
登録日時: 7年前
連絡を取る:

マップ表示プログラムのデバック中に例外がスローされた。

#1

投稿記事 by keito94 » 7年前

アクションゲームを制作する一環でマップ表示プログラムを作ってみたのですが、以下のような例外がスローされて、実行できません。
エラー対策などはしっかり調べて、しっかり対処しました。したつもりです。
Mapping.cpp

コード:

#pragma once
#include "fmfmap.h"
extern CFmfMap MapObj;
extern int MapBitCount;
extern int MapGraph;
//マップチップサイズ
const int MAP_CELL = 16;
Main.cpp

コード:

#include "Main.h"
#include "Player.h"
#include "Stage.h"
#include "Mapping.h"

CGameMain Main;
//ステージデータのクラスを生成する。
CStage *Stage;
CFmfMap MapObj;

int CGameMain::MapLoad(const char* file_name, int stage_num) {
	MapBitCount = MapObj.GetLayerBitCount() == 8 ? 16 : 256;
	if (!MapObj.Open(file_name)) {
		return -1;
	}
	BYTE* layer = (BYTE*)MapObj.GetLayerCount();
	if (layer == NULL) {
		return -1;
	}
	return 0;
}

int CGameMain::Init() {
	ChangeWindowMode(TRUE), SetGraphMode(320, 240, 32);
	//DXライブラリの初期化エラーが発生したときに終了。
	if (DxLib_Init() == -1) { return -1; }
	Time = GetNowCount();
	SetDrawScreen(DX_SCREEN_BACK);
	SetWaitVSyncFlag(FALSE);
	MapLoad("テスト用.fmf", 0);
	LoadDivGraph("マップチップ.bmp", 2, 2, 1, 16, 16, MapGraph, FALSE);
	int InitX = 0.0F, InitY = 0.0F;
	Player = new CPlayer(InitX,InitY);
	Player->Init();
	return 0;
}

void CGameMain::Main() {
	Time = GetNowCount();
	//1/60秒立つまで待つ
	while(GetNowCount()-Time<1000/60){}
	Player->Update();
	Stage->DrawStage();
	Player->Draw();
}

void CGameMain::Fin() {
	Player->Fin();
	delete Player;
	DxLib_End();
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
	Main.Init();
	while (ScreenFlip() == 0 && ProcessMessage() == 0 && ClearDrawScreen() == 0) {
		Main.Main();
	}
	Main.Fin();
	return 0;
}
Main.h

コード:

class CGameMain {
	int Time;
	CPlayer *Player;
public:
	int MapGraph[2];
	int StageIndex;
	int GameMap;
	int MapLoad(const char* file_name, int stage_num);
	int Init();
	void Main();
	void Fin();
};
Stage.h

コード:

#pragma once
class CStage {
public:
	int MapGraph[2];
	float ScrollX, ScrollY;
	const char* Name;
	int Score, Time;
	CStage(const char* name) : Name(name) {}
	virtual void Init() {}
	virtual void Destroy() {}
	virtual bool Move() { return true; }
	virtual void Draw() {};
	void DrawStage();
};
Stage.cpp

コード:

#include "Stage.h"
#include "Mover.h"
#include "Player.h"

void CStage::DrawStage() {
	DWORD cwidth = MapObj.GetChipWidth();
	DWORD cheight = MapObj.GetChipHeight();
	int index, src_x, src_y;
	for (int y = 0; y < 15; y++) {
		for (int x = 0; x < 20; x++) {
			index = MapObj.GetValue(0, x, y);
			src_x = (index % MapBitCount) * cwidth;
			src_y = (index / MapBitCount)*cheight;
			DrawRectGraph((int)(x*MAP_CELL), (int)(y*MAP_CELL), src_x, src_y, MAP_CELL, MAP_CELL, MapGraph[index], TRUE, FALSE);	//ここで例外が起こっている。
		}
	}
}
(これだけでは動かないことをご了承ください。)
エラーコードは以下のとおりです。

コード:

0x0067C8DA で例外がスローされました (スタアド.exe 内): 0xC0000005: 場所 0x00000008 の読み取り中にアクセス違反が発生しました
最後に編集したユーザー keito94 on 2017年4月08日(土) 13:39 [ 編集 2 回目 ]
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

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

Re: マップ表示プログラムのデバック中に例外がスローされた。

#2

投稿記事 by YuO » 7年前

keito94 さんが書きました:アクションゲームを制作する一環でマップ表示プログラムを作ってみたのですが、以下のような例外がスローされて、実行できません。
例外がスローされている以上,実行されていると思いますが。
keito94 さんが書きました:

コード:

0x0067C8DA で例外がスローされました (スタアド.exe 内): 0xC0000005: 場所 0x00000008 の読み取り中にアクセス違反が発生しました
0xC0000005は有効でないメモリへのアクセスです (元々はハードウェア例外)。
0x00000008へのアクセスだから,int型の配列の2番目の要素へのアクセスなどが発生しているのだと思います。

アクセス時の変数やメンバ変数の値,場合によってはthisの値を調べて,呼び出し履歴を辿るなりしておかしい部分を探してみてはどうでしょうか。

アバター
沖 滉均
記事: 237
登録日時: 13年前
住所: K県F市

Re: マップ表示プログラムのデバック中に例外がスローされた。

#3

投稿記事 by 沖 滉均 » 7年前

keito94 さんが書きました:エラー対策などはしっかり調べて、しっかり対処しました。
昨日も書いたことの繰り返しにもなりますが何をしたのですか?
何を調べたのか、その結果何がわかって何がわからなかったのか
そういう質問の方が良いアドバイスが得られる可能性が高いと思います。

コードは載せてるし、例外も載せてはいますがkeito94さんは何をしたのでしょうか?
コードを載せるだけでは、具体的な質問内容にはなっていませんので、YuOさんのおっしゃっているように
YuO さんが書きました: アクセス時の変数やメンバ変数の値,場合によってはthisの値を調べて,呼び出し履歴を辿るなりしておかしい部分を探してみてはどうでしょうか
などやってみてその結果を出したうえで質問してはいかがでしょうか?
There is no royal road to learning.
codeタグで指定できる言語
画像

アバター
keito94
記事: 264
登録日時: 7年前
連絡を取る:

Re: マップ表示プログラムのデバック中に例外がスローされた。

#4

投稿記事 by keito94 » 7年前

沖さんの仰る通り、知識不足でした。しっかりデバックしたいと思います…。
ところで、アクセス時の変数を見てみたところ、こんなものを発見しました。
おそらくこれが例外がスローされる原因だと思います。

コード:

-		MapGraph	0x00000004 {???, ???}	int[2]
		[0]	<メモリを読み取れません>	
		[1]	<メモリを読み取れません>	
この場合、どうすればいいのでしょうか。
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

たいちう
記事: 418
登録日時: 13年前

Re: マップ表示プログラムのデバック中に例外がスローされた。

#5

投稿記事 by たいちう » 7年前

> この場合、どうすればいいのでしょうか。

C++の言語知識が非常に不足しています。基本を勉強する気はないのですか?
人が作ったプログラムをコピーするだけで、それなりのプログラムが動きますが、
それはあなたの実力ではありません。

ポインタの存在すら知らなかったようなので、入門書が必要だと思います。
今回のエラーも基本的なポインタの使い方を勉強することで解決するでしょう。

アバター
durandal
記事: 11
登録日時: 7年前
住所: 長野県

Re: マップ表示プログラムのデバック中に例外がスローされた。

#6

投稿記事 by durandal » 7年前

Stage.cpp の11行で

コード:

            index = MapObj.GetValue(0, x, y);
とGetValue関数の戻り値を 変数indexに代入していますが、
Stage.hの4行目で

コード:

   int MapGraph[2];
と宣言しているため、GetValue関数の戻り値が0か1でないと Stage.cppの14行目のDrawRectGraph関数でアクセス違反が発生します。
そのため、エラー確認の意味も含めて、変数indexの値(=GetValue関数の戻り値)が適切かどうかを確認する処理を加えたらいかがでしょうか。

アバター
keito94
記事: 264
登録日時: 7年前
連絡を取る:

Re: マップ表示プログラムのデバック中に例外がスローされた。

#7

投稿記事 by keito94 » 7年前

たいちうさんの発言でC++知識のなさを改めて実感しました。
shino0526yさん、変数indexの値のエラー確認のルーチンを教えてくれませんか?
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

アバター
usao
記事: 1887
登録日時: 11年前

Re: マップ表示プログラムのデバック中に例外がスローされた。

#8

投稿記事 by usao » 7年前

オフトピック
> この場合、どうすればいいのでしょうか。

そんなこと言われても,

アクセス先の中身の値が問題なのか
アクセスしていること自体がバグなのか
それとも別の何かなのか

他者には全く不明なのだから
どうするのが正しいのかは,おそらくあなたにしかわからないわけで…


提示コードでは,
CStage *Stage;
が,何かしら妥当なオブジェクトを指しているのかもわからないので,

>変数index

がどうのこうのとかいう場所まで走っているのかも不明.

アバター
keito94
記事: 264
登録日時: 7年前
連絡を取る:

Re: マップ表示プログラムのデバック中に例外がスローされた。

#9

投稿記事 by keito94 » 7年前

keito94 さんが書きました: この場合、どうすればいいのでしょうか。
…では、よくわかりませんでしたね…。
アクセス先の中身の値に問題があるようです。ならわかりますかね?
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

アバター
keito94
記事: 264
登録日時: 7年前
連絡を取る:

Re: マップ表示プログラムのデバック中に例外がスローされた。

#10

投稿記事 by keito94 » 7年前

例外処理を使って、indexが、適切かどうかを調べてみたら、変数indexに問題は見つかりませんでした。

コード:

			try {
				index = MapObj.GetValue(0, x, y);
				if (index == NULL)
					throw 1;
			}
			catch (int) {
				int flag;
				flag = MessageBox(
					NULL,
					TEXT("マップの値が不正です!!"),
					TEXT("エラー!!"),
					MB_ICONWARNING | MB_OK);
			}
それどころか、アクセス先の中身の値の問題がたくさん発覚しました…。

コード:

-		MapGraph	0x00000004 {???, ???}	int[2]
		[0]	<メモリを読み取れません>	
		[1]	<メモリを読み取れません>	
		ScrollX	<メモリを読み取れません>	
		ScrollY	<メモリを読み取れません>	
		Name	<メモリを読み取れません>	
		Score	<メモリを読み取れません>	
		Time	<メモリを読み取れません>	
		index	1	int//ここは正常
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

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

Re: マップ表示プログラムのデバック中に例外がスローされた。

#11

投稿記事 by YuO » 7年前

keito94 さんが書きました:この場合、どうすればいいのでしょうか。
ちゃんと,デバッグすればよいです。
ただ,それだけです。
shino0526y さんが書きました:と宣言しているため、GetValue関数の戻り値が0か1でないと Stage.cppの14行目のDrawRectGraph関数でアクセス違反が発生します。
残念ながら,よっぽど変わった値でない限り,0x00000008へのアクセスは起きません。
0x00000008へのアクセス違反という事実から,((T*)nullptr)->fooみたいなアクセスが一番考えられる事です。
keito94 さんが書きました:shino0526yさん、変数indexの値のエラー確認のルーチンを教えてくれませんか?
変数の値なんて,ブレークポイント作って止めれば調べられます。
keito94 さんが書きました:例外処理を使って、indexが、適切かどうかを調べてみたら、変数indexに問題は見つかりませんでした。
原因候補はindexだけではありません。

このNo.4の回答にて,ご自分でMapGraphのポインタの値がおかしいことを示していますよね。
そちらをまずは解決すべきではないでしょうか。
# 私は最初にthisの値を調べる,ということを書いています。
  • エラーが起きた時のthisの値はいくつでしたか。
  • 呼び出し履歴を一つずつ戻っていったときに,その時点の変数の値は正しい値でしたか。
こういうことをひとつずつ調べていって,バグを潰す作業が「デバッグ」です。
ちゃんとデバッグを行いましょう。
オフトピック
過去に,スクショ付きで簡単にデバッグの手順を書いた事があります。
http://dixq.net/forum/viewtopic.php?f=3&t=17999#p138073
昔はこういうのが入門書にも載っていたのですが,最近はあまりみかけなくなりましたね。

梅衣堂ひよ
記事: 24
登録日時: 7年前

Re: マップ表示プログラムのデバック中に例外がスローされた。

#12

投稿記事 by 梅衣堂ひよ » 7年前

F10で起動してF10とF11を用いて一度ソースを1行ずつ丁寧にデバッグしてはどうですか?
オフトピック
他人のソースをコピペしたり質問をしてそのまま実装したりするのを悪いとは言いませんが、その意味を理解していないと何かあった時他者の手助け無しではバグ取りの1つもできない事態に陥ります。
配列の仕組みなども含めたポインタ全体の勉強を一度しっかり時間をかけて理解するまでやることをお勧めします。
結構説明が下手ですのでご了承ください。割と言葉が足りなかったり文字だらけで分かりにくかったりします。

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

Re: マップ表示プログラムのデバック中に例外がスローされた。

#13

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

keito94 さんが書きました:エラー対策などはしっかり調べて、しっかり対処しました。
しっかり対処していないからエラーが出るんですよね?
「しっかり対処したつもりです」の間違いですよね?
keito94 さんが書きました:

コード:

			DrawRectGraph((int)(x*MAP_CELL), (int)(y*MAP_CELL), src_x, src_y, MAP_CELL, MAP_CELL, MapGraph[index], TRUE, FALSE);	//ここで例外が起こっている。
keito94 さんが書きました:

コード:

0x0067C8DA で例外がスローされました (スタアド.exe 内): 0xC0000005: 場所 0x00000008 の読み取り中にアクセス違反が発生しました
まず、この行でポインタを扱うのはMapGraph[index]しかありません。
MapGraphがどこで定義されているのかを調べると、CStageのメンバ変数のようです。
これは2要素固定の配列でありポインタではないので、ここがNULLになることは無いと思っていいでしょう。
そこで、次に CStage::DrawStage()がどこで使用されているかを調べます。
その結果は、提示されたコードで使用されているのはMain.cppの43行目のStage->DrawStage();のみのようです。
このStageがどこで定義されているかを調べると、この関数のローカル変数やCGameMainのメンバ変数には無く、グローバル変数で定義されているようです。
"Stage"で検索してみましたが、提示されたコードにStageに代入している場所は無いようです。
従って、CFmfMapなどのコードが無いので確定は出来ませんが、グローバル変数なのでNULLに初期化されているStageをそのままデリファレンスしてメンバ関数を呼び出したことでエラーになっている疑いがあります。
keito94 さんが書きました:例外処理を使って、indexが、適切かどうかを調べてみたら、変数indexに問題は見つかりませんでした。

コード:

			try {
				index = MapObj.GetValue(0, x, y);
				if (index == NULL)
					throw 1;
			}
			catch (int) {
				int flag;
				flag = MessageBox(
					NULL,
					TEXT("マップの値が不正です!!"),
					TEXT("エラー!!"),
					MB_ICONWARNING | MB_OK);
			}
このコードはどういう意味ですか? (どういう意味だと思っていますか?)
indexはint型ですよね?どうしてNULL (0に近いが、通常はポインタとの比較やポインタ変数への代入にのみ用いる) と比較しているのですか?
indexが0ではいけないということは、0未満でも2以上でも範囲外へのアクセスが発生するので、indexは1であるはずという仕様なのですか?

[hr]
gcc/g++およびgdbというツールを用いると、ソースコードのどこでアクセス違反が発生したかがわかります。
これにより、エラーの原因を考えるヒントを得ることができます。

例えば、このコード(test.cpp)

コード:

#include <iostream>

struct Hoge {
	int foo[2];
	virtual void poyo() {}
	void useFoo();
};

void Hoge::useFoo() {
	std::cout << foo[1] << '\n';
}

Hoge* hogeValue;

void bar() {
	hogeValue->useFoo();
}

int main() {
	bar();
}
のどこでアクセス違反が発生するかを調べるには、

1. g++で-g3オプション(デバッグ情報を出力する)をつけてコンパイルする。
2. コンパイルしたプログラムを指定し、gdbを実行する。
3. runコマンドでプログラムを走らせる。
4. アクセス違反が出たら、どこで出たかが表示される。
5. この時、whereコマンドでそれがどこから呼び出されたかを調べることができる。

のようにするとわかります。

実行例

コード:

YUKI.N>g++ -g3 -static -o test test.cpp

YUKI.N>gdb test
GNU gdb (GDB) 7.6.1
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "mingw32".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from D:\gdbtest\test.exe...done.
(gdb) run
Starting program: D:\gdbtest/test.exe
[New Thread 5900.0x618]

Program received signal SIGSEGV, Segmentation fault.
0x004013ec in Hoge::useFoo (this=0x0) at test.cpp:10
10              std::cout << foo[1] << '\n';
(gdb) where
#0  0x004013ec in Hoge::useFoo (this=0x0) at test.cpp:10
#1  0x00401423 in bar () at test.cpp:16
#2  0x00401435 in main () at test.cpp:20
(gdb) quit
A debugging session is active.

        Inferior 1 [process 5900] will be killed.

Quit anyway? (y or n) y

YUKI.N>
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
keito94
記事: 264
登録日時: 7年前
連絡を取る:

Re: マップ表示プログラムのデバック中に例外がスローされた。

#14

投稿記事 by keito94 » 7年前

ごめんなさい。プロジェクトを一から作り直したいと思います。
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

たいちう
記事: 418
登録日時: 13年前

Re: マップ表示プログラムのデバック中に例外がスローされた。

#15

投稿記事 by たいちう » 7年前

むしろ、このプログラムはあなたにはまだ早すぎます。
作り直すというよりも、言語の基本を一通り勉強してから、再チャレンジするのがよいと思います。

アバター
keito94
記事: 264
登録日時: 7年前
連絡を取る:

Re: マップ表示プログラムのデバック中に例外がスローされた。

#16

投稿記事 by keito94 » 7年前

たいちう さんが書きました:むしろ、このプログラムはあなたにはまだ早すぎます。
作り直すというよりも、言語の基本を一通り勉強してから、再チャレンジするのがよいと思います。
ちょうどいま、C++の勉強をしていたところです。
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

返信

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