@デバッグなし
Run-Time Check Failure #2 - Stack around the variable 'fn' was corrupted.
@デバッグあり
Run-Time Check Failure #2 - Stack around the variable 'ck' was corrupted.
というデバッグエラーが出ます。
ソースコードは、STGのリプレイのためのデータを保存・読み込みするという内容です。
#include "DxLib.h"
#include <fstream>
#include <vector>
#include <bitset>
using namespace std;
enum{TITLE, SAVE, REPLAY};
enum{KEY_Z, KEY_X, KEY_C, KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT, KEY_ENTER, KEY_NUM};
struct KeyData{
bool key[8];
};
int gSta; //・・・・・・・・タイトル画面・リプレイデータ保存画面・リプレイ画面のどれが現在の画面かを示す
bool menu; //タイトル画面で リプレイデータ保存・リプレイ のどちらを選ん[だ/でいる]かを示す
char key[256];//・・・・・・・すべてのキーの押下状態を記憶する
int keyTrig; //連続キー入力を無効にする
int arrow;//・・・・・・・・・矢印画像のハンドルを記憶
char keyLog[KEY_NUM]; //1つ前のフレームのキーの押下状態を記憶
int frameCou; //タイトル画面から移行した後、現在何フレーム目かを示す
int nextChArr; //・・・・・・chTime,chKey の何番目の要素を次回に取り出せばよいかを示す
vector<int> chTime; //何フレーム目にキー状態の変更があったかを記憶
vector<KeyData> chKey; //・・・キーが変更された時のキー状態を記憶
int x, y; //矢印画像の座標を記憶
int gh; //自機画像のハンドルを記憶
int bomCou; //ボム用
void ReOpenFile(ofstream &, int); //書き込み時、1回でファイルが開けなかった場合3回までトライ
void ReReadFile(ifstream &, int); //読み込み時、以下同文
void KeyInit(); //キー状態のログを変数に記憶させる関数
int WINAPI WinMain(HINSTANCE hI, HINSTANCE hP, LPSTR lpC, int nC){
ChangeWindowMode(TRUE);
SetOutApplicationLogValidFlag(FALSE);
if(DxLib_Init() == -1) return(-1);
SetDrawScreen(DX_SCREEN_BACK);
//画像読み込み
arrow = LoadGraph("media\\arrow.PNG");
gh = LoadGraph("media\\me.PNG");
while(ProcessMessage() == 0 && CheckHitKey(KEY_INPUT_ESCAPE) == 0){
ClsDrawScreen();
GetHitKeyStateAll(key); //全てのキー状態を取得
if(keyTrig) --keyTrig; //連続キー入力の無効期間を減少
switch(gSta){
//タイトル画面の処理
case TITLE:
//↑キー又は↓キーが押されたら選択しているモードをもう一方のものにする
if(keyTrig==0){
if(key[KEY_INPUT_UP] || key[KEY_INPUT_DOWN]){
menu = !menu;
keyTrig = 15;
}
}
//選択肢、矢印の描画
SetFontSize(32);
{
int fx = 320-GetDrawStringWidth("リプレイデータ作成",18)/2;
DrawString(fx,240-32, "リプレイデータ作成", GetColor(0,255,0) );
DrawString(fx,240, "リプレイ", GetColor(0,255,0) );
DrawGraph(fx-32,240-32+32*menu, arrow, TRUE);
}
//上下矢印キー以外のキーが押されていたら選択されたモードに移る
{
int num = 0;
for(int i=0;i<256;++i) num += key[i];
if(num-key[KEY_INPUT_UP]-key[KEY_INPUT_DOWN] && keyTrig==0){
//上下矢印キー以外のキーが押されており、連続キー入力でない場合の処理
gSta = SAVE+menu; //選択されたモードに移るようにする
//データの初期化
for(int i=0;i<8;++i) keyLog[i]=0;
frameCou=0;
nextChArr=0;
x=0, y=0;
bomCou=0;
keyTrig = 15;
//リプレイモードが選択された場合
if(menu){
//リプレイデータの読み込み
ifstream ifs("ReplayData.dat", ios::binary); //ファイルをバイナリモードで開く
if(!ifs) ReReadFile(ifs, 0); //開けなかったら3回までリトライ
//ファイルが開けたら
if(!ifs==0){
while(TRUE){
{
//「キー状態が変更されたフレーム」の情報を取得して記憶
int fn;
ifs.read( (char *)&fn, sizeof(int) );
chTime.push_back(fn);
}
{
char ck;
int nowP;
{
KeyData kd;
//「どのキーの状態が変更されたか」の情報を取得して記憶
ifs.read(&ck, sizeof(kd.key) );
memcpy(&kd.key[0], &ck, sizeof(kd.key) );
chKey.push_back(kd);
}
//ファイルの終端に達していればwhile文から脱出
nowP = ifs.tellg(); //現在の場所を記憶
ifs.seekg(0, fstream::end); //ファイルの終端に移動
if(nowP>=ifs.tellg() ) break; //while文から脱出
else{
//読み取る位置を元に戻す
ifs.clear();
ifs.seekg(nowP);
}
}
}
}
//↑ファイルが開けたら
}
//リプレイデータ保存モードが選択された場合リプレイデータを空にする
else{
ofstream ofs("ReplayData.dat");
if(!ofs) ReOpenFile(ofs, 0);
}
}
}
break;
//リプレイデータ保存画面の処理
case SAVE:
{
//キー状態を確認
bool changed = FALSE; //どのキーも変更されていない設定にする
//以前のキー状態と比較して、違っていればキーが変更されている設定にする
if(keyLog[KEY_Z] != key[KEY_INPUT_Z]) changed = TRUE;
if(keyLog[KEY_X] != key[KEY_INPUT_X]) changed = TRUE;
if(keyLog[KEY_C] != key[KEY_INPUT_C]) changed = TRUE;
if(keyLog[KEY_UP] != key[KEY_INPUT_UP]) changed = TRUE;
if(keyLog[KEY_DOWN] != key[KEY_INPUT_DOWN]) changed = TRUE;
if(keyLog[KEY_LEFT] != key[KEY_INPUT_LEFT]) changed = TRUE;
if(keyLog[KEY_RIGHT] != key[KEY_INPUT_RIGHT]) changed = TRUE;
if(key[KEY_INPUT_RETURN] && keyTrig==0) changed = TRUE;
KeyInit(); //キー状態のログを残す
//キー状態が変更されていれば、フレーム数と共に保存
if(changed == TRUE){
ofstream ofs("ReplayData.dat", ios::binary | ios::app);
if(!ofs) ReOpenFile(ofs, 0);
if(!ofs == 0){
//データ処理
KeyData kd;
kd.key[0] = (key[KEY_INPUT_Z]==1);
kd.key[1] = (key[KEY_INPUT_X]==1);
kd.key[2] = (key[KEY_INPUT_C]==1);
kd.key[3] = (key[KEY_INPUT_UP]==1);
kd.key[4] = (key[KEY_INPUT_DOWN]==1);
kd.key[5] = (key[KEY_INPUT_LEFT]==1);
kd.key[6] = (key[KEY_INPUT_RIGHT]==1);
kd.key[7] = (key[KEY_INPUT_RETURN]==1);
//書き込み
ofs.write( (char *)&frameCou, sizeof(int) );
ofs.write( (char *)&kd.key[0] , sizeof(kd.key) );
}
}
}
//↓↓ switch文から脱出せずに下の処理へ ↓↓
//キー状態に応じた処理
case REPLAY:
{
bool endFlag = 0;
//リプレイ画面固有の処理。キー状態を改ざんして、リプレイデータと同期させる
//変更があったフレームならばキー状態を変更する
if(gSta==REPLAY){
if(frameCou==chTime[nextChArr]) ++nextChArr;
key[KEY_INPUT_Z] = chKey[nextChArr+(-1)*(nextChArr!=0)].key[KEY_Z]*(nextChArr!=0);
key[KEY_INPUT_X] = chKey[nextChArr+(-1)*(nextChArr!=0)].key[KEY_X]*(nextChArr!=0);
key[KEY_INPUT_C] = chKey[nextChArr+(-1)*(nextChArr!=0)].key[KEY_C]*(nextChArr!=0);
key[KEY_INPUT_UP] = chKey[nextChArr+(-1)*(nextChArr!=0)].key[KEY_UP]*(nextChArr!=0);
key[KEY_INPUT_DOWN] = chKey[nextChArr+(-1)*(nextChArr!=0)].key[KEY_DOWN]*(nextChArr!=0);
key[KEY_INPUT_LEFT] = chKey[nextChArr+(-1)*(nextChArr!=0)].key[KEY_LEFT]*(nextChArr!=0);
key[KEY_INPUT_RIGHT] = chKey[nextChArr+(-1)*(nextChArr!=0)].key[KEY_RIGHT]*(nextChArr!=0);
key[KEY_INPUT_RETURN] = chKey[nextChArr+(-1)*(nextChArr!=0)].key[KEY_ENTER]*(nextChArr!=0);
if(chKey[nextChArr-1].key[KEY_ENTER]) endFlag = TRUE; //エンターキーが押されていたら問答無用で終了
}
//エンターキーが押されていたらタイトル画面に戻る
if( (key[KEY_INPUT_RETURN] && keyTrig==0) || endFlag){
gSta = TITLE;
keyTrig = 15;
}
}
//矢印キーの状態に応じて自機の座標をいじる
x += (10-5*key[KEY_INPUT_X])*key[KEY_INPUT_RIGHT] -(10-5*key[KEY_INPUT_X])*key[KEY_INPUT_LEFT];
y += (10-5*key[KEY_INPUT_X])*key[KEY_INPUT_DOWN] -(10-5*key[KEY_INPUT_X])*key[KEY_INPUT_UP];
//ボムの処理
if(bomCou==0){if(key[KEY_INPUT_C]) bomCou = 255;}
else --bomCou;
SetDrawBlendMode(DX_BLENDMODE_ALPHA, bomCou);
if(bomCou) DrawCircle(x+16,y+16, 255-bomCou, GetColor(255,255,255), TRUE);
SetDrawBlendMode(DX_BLENDMODE_NOBLEND, 0);
DrawGraph(x,y, gh, TRUE); //自機描画
break;
}
++frameCou;
ScreenFlip();
}
DxLib_End();
return(0);
}
void ReOpenFile(ofstream &ofs, int num){
ofs.open("ReplayData.dat", ios::binary | ios::app);
++num;
if(!ofs){
if(num<3) ReOpenFile(ofs, num);
}
}
void ReReadFile(ifstream &ifs, int num){
ifs.open("ReplayData.dat", ios::binary);
++num;
if(!ifs){
if(num<3) ReReadFile(ifs, num);
}
}
void KeyInit(){
//キー状態のログを残す
keyLog[KEY_Z] = key[KEY_INPUT_Z];
keyLog[KEY_X] = key[KEY_INPUT_X];
keyLog[KEY_C] = key[KEY_INPUT_C];
keyLog[KEY_UP] = key[KEY_INPUT_UP];
keyLog[KEY_DOWN] = key[KEY_INPUT_DOWN];
keyLog[KEY_LEFT] = key[KEY_INPUT_LEFT];
keyLog[KEY_RIGHT] = key[KEY_INPUT_RIGHT];
}
原因・解決方法がわかる方、よろしくお願いいたします。
また、デバッグ方法もぜひ教えてください。