🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
DXライブラリ

DXライブラリとは、DirectXを使ったWindowsソフトの開発に必ず付いて回るDirectXやWindows関連のプログラムを使い易くまとめた形で利用できるようにしたC++言語用のゲームライブラリです。

Q&A

解決済

2回答

1436閲覧

謎のバッファオーバーランの原因が知りたい

退会済みユーザー

退会済みユーザー

総合スコア0

DXライブラリ

DXライブラリとは、DirectXを使ったWindowsソフトの開発に必ず付いて回るDirectXやWindows関連のプログラムを使い易くまとめた形で利用できるようにしたC++言語用のゲームライブラリです。

0グッド

0クリップ

投稿2019/12/06 15:14

編集2019/12/08 11:48

コメント部の///////////部のコードで例外が発生しましたmove->でメモリが読めませんのエラーが発生する原因が知りたいです。

またそのコメント部のコードをコメントにするとこんどはControl関数部の落下管理のBlock_Donw関数のmove->yの処理で同じ例外が発生しています、これは何をしたいのでしょうか?値を画面に出力してみたり色々試しましたがどうしても原因がわかりません。そもそもポインタの移動などはおこなっていないのでそもそもおかしいと思っています。

start.h

/*シーン管理*/ enum class SceneType { Title, Game, GameOver, Pause }; extern SceneType nowScene; class Scene { private: std::unique_ptr<Title> t; std::unique_ptr<Game> g; public: Scene(); void Update(); void Draw_Update(); ~Scene(); }; #endif

start.cpp

/*コンストラクタ*/ Scene::Scene(): // nowScene(Scene::Title), t(std::make_unique<Title>()), g(std::make_unique<Game>()) { } //SceneType nowScene = SceneType::Title; SceneType nowScene = SceneType::Title; /*計算*/ void Scene::Update() { switch(nowScene) { case SceneType::Title: { t->Update(); break; }; case SceneType::Game: { g->Update(); break; } } } /*描画*/ void Scene::Draw_Update() { switch (nowScene) { case SceneType::Title: { t->Draw_Update(); break; }; case SceneType::Game: { g->Draw_Update(); break; } } } /*デストラクタ*/ Scene::~Scene() { }

Game.h

#ifndef ___GAME_h #define ___GAME_h #include <array> #include <memory> /* 画面サイズ: 1280,720 ステージサイズ: 288,504 */ #define STAGE_X 12 #define STAGE_Y 21 #define STAGE_FRAME -1 #define CELL 24 #define STAGE_EMPTY 0 class Game { private: /*画像情報*/ int Image_Block[8];//ブロック各種 int Image_gback_ground;//背景 int Image_frameY;//背景 int Image_frameX;//背景 /*データ*/ int Data_Block[8][4][4][4]; class Position { public: int x; int y; Position(): x(0),y(0){ } }; /*キー状態*/ enum class keyState { Left, Right, Down, Rotation, eHold, Invalid, Pause, }; // std::array<std::array<int, 12>,21> stage = {{ int stage[STAGE_Y][STAGE_X] = { {-1,0,0,0,0,0,0,0,0,0,0,-1}, //////////////////////行数の問題で割愛 {-1,0,0,0,0,0,0,0,0,0,0,-1}, {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1}, }; int blockHold; //ホールドしてるブロックを記録 keyState* key; //キー入力管理 keyState* keyAction; //キー入力管理 keyState* keyPause; //キー入力管理 //Position *move; //プレイヤ座標 std::unique_ptr<Position> move; //プレイヤ座標 int nRote; //回転 int nowNumber; //ブロック const int color_index[7]; //色情報  public: Game(); void Update(); void Draw_Update(); ~Game(); private: //割愛 }; #endif
/*コンストラクタ*/ Game::Game(): Data_Block { { { },              ////////////////文字数の関係で割愛 { {1,1,0,0}, {0,0,0,0}, {0,0,0,0}, }, { {1,0,0,0}, {1,1,0,0}, {0,1,0,0}, {0,0,0,0}, }, }, { { {1,1,0,0}, {0,1,1,0}, {0,0,0,0}, {0,0,0,0}, }, { {0,1,0,0}, {1,1,0,0}, {1,0,0,0}, {0,0,0,0}, }, { {1,1,0,0}, {0,1,1,0}, {0,0,0,0}, {0,0,0,0}, }, { {0,1,0,0}, {1,1,0,0}, {1,0,0,0}, {0,0,0,0}, }, }, { { {1,0,0,0}, {1,1,1,0}, {0,0,0,0}, {0,0,0,0}, }, { {1,1,0,0}, {1,0,0,0}, {1,0,0,0}, {0,0,0,0}, }, { {1,1,1,0}, {0,0,1,0}, {0,0,0,0}, {0,0,0,0}, }, { {0,1,0,0}, {0,1,0,0}, {1,1,0,0}, {0,0,0,0}, }, }, { { {0,0,1,0}, {1,1,1,0}, {0,0,0,0}, {0,0,0,0}, }, { {1,0,0,0}, {1,0,0,0}, {1,1,0,0}, {0,0,0,0}, }, { {1,1,1,0}, {1,0,0,0}, {0,0,0,0}, {0,0,0,0}, }, { {1,1,0,0}, {0,1,0,0}, {0,1,0,0}, {0,0,0,0}, }, }, { { {0,1,0,0}, {1,1,1,0}, {0,0,0,0}, {0,0,0,0}, }, { {1,0,0,0}, {1,1,0,0}, {1,0,0,0}, {0,0,0,0}, }, { {1,1,1,0}, {0,1,0,0}, {0,0,0,0}, {0,0,0,0}, }, { {0,1,0,0}, {1,1,0,0}, {0,1,0,0}, {0,0,0,0}, }, }, }, move(new Position()), key(new keyState), keyAction(new keyState), keyPause(new keyState), nRote(0), color_index{ 5,3,4,1,6,2,7 } { srand((unsigned int)time(NULL)); LoadDivGraph("Tetris/resource/Block_tmp_24px.png", 8, 4, 2, 24, 24, Image_Block); Image_frameX = LoadGraph("Tetris/resource/Image_frameX.png"); Image_frameY = LoadGraph("Tetris/resource/Image_frameY.png"); // nowNumber = rand() % 7 == 0; set_Rand(); move->x = 4; move->y = 1; } // ------------------------------------------------------------------------------- // 計算 // ------------------------------------------------------------------------------- /*ブロック種類の乱数を引く*/ void Game::set_Rand() { //ofs << move->x << ",aaaaaaaa, " << move->y << endl; while(nowNumber % 7 != 0){ ofs<<nowNumber<<endl; nowNumber = rand() % 7; } } /*ブロックを生成*/ void Game::Create_Block() { //set_Rand(); ofs << "aaaaaaaaaaa"<< endl; //ofs << &move->x << "," << &move->y << endl; //int a = move->x; //ofs << a<< endl; //move->x = 4; //move->y = 0; } /*ブロック削除*/ void Game::Block_Clear() { } /*ブロック落下と移動管理*/ bool Game::Block_Down() { move->y += 1; if (Collision_X() == true) { move->y += - 1; return true; }else{ move->y += 1; return false; } } /*指定したピースの座標にブロックがあるかどうか?*/ bool Game::get_isBlock(int n, int r, Position p) { return Data_Block[n][r][p.y][p.x]; } /*ステージ座標に何があるか返す 1 壁 2 ブロック 0 何もなし*/ int Game::get_Stage(int x,int y) { return stage[y][x]; } /*ステージにブロック情報を入れてる*/ void Game::set_Stage(int x,int y,int c) { stage[y][x] = c; } /*当たり判定*/ bool Game::Collision_X() { Position p; for (int y = 0; y < 4; y++) { for (int x = 0; x < 4; x++) { p.x = x; p.y = y; if( get_isBlock(nowNumber,nRote,p) == true && get_Stage(move->x + x,move->y + y) != 0 ) { return true; } } } return false; } /*ブロックを固定する*/ void Game::Put_Block() { int dx = move->x; int dy = move->y; for(int py = 0; py < 4; py++) { for(int px = 0; px < 4; px++) { //ofs << move->x << " , " << move->y << endl; //ofs << color_index[nowNumber] <<endl; //set_Stage((move->x + px), (move->y + py), color_index[nowNumber]); set_Stage( (dx + px) ,(dy + py),color_index[nowNumber]); // ofs << "eee" << endl; } } } /*キー入力受付・移動処理・当たり判定*/ void Game::Control() { if (Fps::keyboard(KEY_INPUT_LEFT) == 1) { // *key = keyState::Left; move->x += -1; if(Collision_X() == true) { move->x += 1; } } else if (Fps::keyboard(KEY_INPUT_RIGHT) == 1) { //*key = keyState::Right; move->x += 1; if (Collision_X() == true) { move->x += -1; } }else if(Fps::keyboard(KEY_INPUT_DOWN) == 1) { *key = keyState::Down; } else{ //*key = keyState::Invalid; // move->x = 0; } /*Xで回転*/ if (Fps::keyboard(KEY_INPUT_X) > 0) { *keyAction = keyState::Rotation; } /*Pキーで一時停止*/ if (Fps::keyboard(KEY_INPUT_P) > 0) { *keyPause = keyState::Pause; } /*落下管理*/ if(Fps::now() % 10 == 0) { if (Block_Down() == true ){ //DrawFormatString(100, 100, GetColor(255, 255, 255), " %d, %d", move->x, move->y, true); Put_Block(); Create_Block(); } } } /*回転処理*/ void Game::Rotate() { } //*********************************************** void Game::Update() { //stage[2][3] = 9; Control(); // Block_Clear(); //DrawFormatString(200, 200, GetColor(255, 255, 255), " nowNumber %d", nowNumber, true); //DrawFormatString(0,0,GetColor(255,255,255),"move: %d,%d",move->x,move->y,true); } //*********************************************** // ------------------------------------------------------------------------------- // 描画 // ------------------------------------------------------------------------------- // ------------------------------------------------------------------------------- void Game::Draw_Update() { //DrawGraph(0,0,back_ground,true); //Draw_Hold(); //Draw_Score(); //Draw_PutBlock(); Draw_frame(); Draw_Block(); //Draw_Next(); } // ------------------------------------------------------------------------------- // ------------------------------------------------------------------------------- /*ハンドルを描画に渡す*/ int Game::get_Block_image() { return color_index[nowNumber]; } /*ブロック描画 (落下中) */ void Game::Draw_Block() { Position p; p.x = 0; p.y = 0; /*要編集*/ for (p.y = 0; p.y < 4; p.y++) { for (p.x = 0; p.x < 4; p.x++) { if (get_isBlock(nowNumber,nRote,p) == 1) { //DrawGraph((move->x + p.x) * CELL,(move->y + p.y) * CELL, getDraw_Block(),true);//////////////////////////////////////////// } } } } /*今のブロックの画像ハンドルを渡す 描画*/ int Game::getDraw_Block() { return Image_Block[nowNumber]; //return 1; } /*ブロック固定描画*/ void Game::Draw_PutBlock() { } void Game::Draw_Score() { } /*ホールド描画*/ void Game::Draw_Hold() { } void Game::Draw_Next() { } /*枠組み*/ void const Game::Draw_frame() { DrawGraph(CELL * 1,CELL * (STAGE_Y - 1), Image_frameX, true); DrawGraph(0,CELL,Image_frameY,true); DrawGraph(CELL * (STAGE_X -1 ), CELL, Image_frameY, true); } /*終了*/ Game::~Game() { }

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yumetodo

2019/12/06 15:48

moveの初期化の問題かなと思いますのでソースコードを提示してください。見えてる範囲に必要なものは載っていません
退会済みユーザー

退会済みユーザー

2019/12/07 09:55

初期化部のコードを追加しました。しかしながら原因が不明です。
yumetodo

2019/12/07 10:01

試しに<memory>をincludeして、moveの型をstd::unique_ptr<Position>にして コンストラクタの move(new Position()), を move() にしてみてください
退会済みユーザー

退会済みユーザー

2019/12/07 10:24

やってみましたが、コンストラクタでのmoveの初期値を設定するコードmove->x = 4;にてnullperでしたというエラーがでました
退会済みユーザー

退会済みユーザー

2019/12/07 10:56

やはり 例外がスローされました:読み取りアクセス違反。 this->move._Mypair._Myval2 が 0x5 でした。 とうエラーが出ます。
guest

回答2

0

ベストアンサー

うーん、これもしかしてバッファーオーバーランじゃないですかね?こうなると問題箇所の絞り込みが人力では困難になってきますというかテクニックがないと無理です。

std::unique_ptrに書き換えたのにエラーってことはmoveを合法的に書き換えるコードがあったら検出できるはずなので、バッファーオーバーランで意図せず書き換わってるんだと思います。

AddressSanitizer (ASan) for Windows with MSVC – C++ Team Blog
に紹介のあるAddressSanitizer とかVSに備わっているコード分析ツールを使って自動解析させてみてください。

これでもだめならDxLibの使ってる関数だけ中身空っぽのモックに差し替えて、Linuxに持っていってvalgrindに掛けるとかしないとだめそう。


遠回りだけど確実な方法はプログラム中でnewもdeleteもmallocもcallocもfreeも書かないことです。代わりにstd::vectorやstd::string、std::uniuqe_ptrやstd::shared_ptrを使います。

それから文字列操作をもししているなら、自力でindexアクセスしたりC標準やDxLibの文字列操作系関数を使わないことです。代わりにstd::stringのメンバー関数やargorithmヘッダーの関数群、fmtlib/fmt(sprintf系関数の代替)を使います。

投稿2019/12/07 12:54

編集2019/12/07 13:07
yumetodo

総合スコア5852

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Bull

2019/12/07 13:35

Visual Studio を使用しているのでしたら、ウォッチで「値が変更された時中断」は使えないでしょうか? std::uniuqe_ptr でも使えるようです。
yumetodo

2019/12/07 13:52 編集

~~あれってBufferoverrun検知できましたっけ?~~いや、できる可能性はあるか。
退会済みユーザー

退会済みユーザー

2019/12/08 04:48

ASan機能を使って実行しましたがDebug版はサポートしていませんと表示されましたのでリリースで実行しましたが普通に実行でき。提示コードと同じ部分で中断されてしまいます。よって現状のままですw
Bull

2019/12/08 05:40

ウォッチはどうでしょうか? もし move が破壊されているとすれば、破壊された時点で止まるはずですが。
退会済みユーザー

退会済みユーザー

2019/12/08 06:48

moveが破壊されているようです。
yumetodo

2019/12/08 10:47

いつのタイミングで?
退会済みユーザー

退会済みユーザー

2019/12/08 11:24

質問内容と同じタイミングです。
Bull

2019/12/08 11:59

move の変更を検知してブレークしているのですよね。 であれば move を書き換えたコードで停止しているはずです。 標準ライブラリの中で止まったとしても、呼び出し履歴でプログラムのどこから呼び出したかがわかります。
yumetodo

2019/12/08 14:43

あと止まったときの他の変数のアドレスをみるとメモリー上で近いものを特定できるかもしれません。
退会済みユーザー

退会済みユーザー

2019/12/08 15:29

プロジェクトの設定のDxLibの設定を間違えた説はあるのでしょうか?一応確認しましたが...
yumetodo

2019/12/08 17:14

関係ないでしょうね。こうなるとソースコード一式をgithubとかに上げていただいて、確認することになりそうですが、問題は私が水曜日くらいまで忙しいということ。
yumetodo

2019/12/10 05:05

ん、解決済になったようですが何かありましたか?
退会済みユーザー

退会済みユーザー

2019/12/10 13:45

私事ですが学校の先生に見てもらいますw
yumetodo

2019/12/11 01:17

あー、なるほど。
退会済みユーザー

退会済みユーザー

2019/12/13 14:14

学校の講師に見てもらいましたがやはりどっかでメモリを誰かが書き換えてるみたいです。
yumetodo

2019/12/14 01:51

それは、まあ、それしかないですよね。問題は誰が?ってところですが。
退会済みユーザー

退会済みユーザー

2020/01/31 14:17

ものすごく今更ですが。原因が解決しました。理由はenum をすべて値型に変更したらなんか動きました。 またその他の変数もすべて値型にしました。
yumetodo

2020/01/31 15:40

???? それ多分型の大きさが変わってたまたまうまく行っただけで、本質的に何も解決してないのでまたなんかの拍子に再発しますよ?
退会済みユーザー

退会済みユーザー

2020/02/01 05:51

なるほど一から作り直すことにしました。
guest

0

どっか他のところでメモリ破壊してます。

CとかC++は、基本的に実行時のエラーチェックってのはしません。
なので、アクセス違反やメモリ破壊が起こってもその時はエラーは出ないことが多いです。
その後の処理で、その破壊されたメモリにアクセスするとかなにかしたときにたまたまエラーが検出される、という挙動になります。
#ひどいときには全くエラーが検出されずに(見た目には正常に)動き続けてしまう

なので、エラーが出た場所のコードは、エラーとは関係がない、ということがよく起こりますね

投稿2019/12/06 23:08

編集2019/12/06 23:10
y_waiwai

総合スコア88038

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2019/12/07 09:57

そうですか、しかしこの場合だとメモリ破壊しそうな処理は一斉書いていません。 またこのGameクラスはstd::uniquer_ptrでメモリ確保していまあす。
y_waiwai

2019/12/07 10:03

あなたが書いてませんと言ってますが、PC君はそう言ってません。 さて、どっちが間違ってるんでしょうか。
退会済みユーザー

退会済みユーザー

2019/12/07 10:25

はい、メモリを破壊するとう処理はたとえばどんな処理なのでしょうか?move->x = 3;ような処理でも場合によっては破壊されてしまうのでしょうか?
yumetodo

2019/12/07 10:41

move自体が書き換えられてるか誤って開放されていると踏んでいるのでunique_ptrへの置き換えを追記依頼に書いたのです。
y_waiwai

2019/12/07 11:12

回答に書いてますが、move->x = 3;のコードが破壊してるんじゃありません。 あなたが提示してる以外のところのコードが破壊してます
退会済みユーザー

退会済みユーザー

2019/12/07 11:20 編集

はい、それは自分も知っています、コメントにしたりして元の原因を探りましたが見つからないので仕方がなく質問を作りました。 また無限ループのコードでg->Updateとg->Draw_Updateというコードをコメントして実行してみましたが普通に実行できました。つまりこのGame.cpp内だと推測しました。
y_waiwai

2019/12/07 11:21

問題を解決したいなら、こちらの求めるものを出しましょう。 なぜコードを全部出さないのでしょう。不都合なところを隠蔽してあなたの得るものはありませんよ。
退会済みユーザー

退会済みユーザー

2019/12/07 12:12

game.hとgmaeクラスを使っているクラスのヘッダーとソースファイルを提示コードに追加しました また支障のない範囲で文字数の関係でコードを省略しています。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問