現在c++でdxlibを用いて、「テキストファイルで指定されたサウンドを流す」というものを作っているのですが、(多分、)テキストファイルの内容を読み込んでそれをvectorクラスの動的配列に代入していく過程でアクセス違反が出てしまいます。
ブレークポイントを設定して調べてみたりしたのですが、エラーの吐き出されるタイミングがまちまちで、エラーの原因がどこにあるのかわかりません。
以下に、コードとエラー(数種類ある(※))を載せますので、原因と解決策をご指南ください。よろしくお願いします。
(※)1回のデバッグにつき1種類のエラーが吐き出されますが、何回かデバッグをしていると、全部で3種類ほどのエラーが出てることが分かりました。いずれも似たような内容のようです。ここでは、取得できた2種類のエラーを載せています。
環境は、Windows10,vs2015,dxlib,c++です。
コード↓
MAIN.cpp
#include<string>
#include"dxlib.h"
#include"Load.h" //データのロード
#include"mainsystem.h" //曲の情報、再生、ステータスを管理
//#include"ui.h" //user interface
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, int nCmdShow) {
//-----primary setting-----//
using namespace std;
ChangeWindowMode(TRUE);
SetAlwaysRunFlag(TRUE);
SetOutApplicationLogValidFlag(FALSE);
SetGraphMode(640, 500, 16);
SetWindowText("エラーから助けてください。お願いします。");
SetWindowIconID(210);
if (DxLib_Init() == -1) { return 0; }
SetDrawScreen(DX_SCREEN_BACK);
//*****起動*****//
int screen_h = MakeScreen(400, 300, TRUE); /タイトル描画用
int title_h = LoadGraph(".\\graphs\\top_title.png");
int titleback_h = LoadGraph(".\\graphs\\top_back.png");
//エフェクト用変数
int x = 0;
bool xturn = false;
int flame = 0;
int show = 300;
int loadstatus = 0;
int dates; //曲の個数
int missed_dates = 0;//ロードに失敗した項目の個数
bool complete = false;
LOAD* load;
MSYS sys;
// UI ui;
load = new LOAD();
while (ScreenFlip() == 0 && ProcessMessage() == 0 && ClearDrawScreen() == 0 && complete == false) {
//-----タイトルなどの描画-----//
/*back*/
DrawGraph(0, 0, titleback_h, TRUE);
/*title*/
SetDrawScreen(screen_h);
DrawGraph(0, 0, title_h, TRUE);
/*effect*/
GraphFilter(screen_h, DX_GRAPH_FILTER_HSB, 0, 0, x, x);
SetDrawScreen(DX_SCREEN_BACK);
DrawGraph(120, 60, screen_h, TRUE);
//-----ファイルのロード処理-----//
switch (loadstatus) {
case 0: //ここは1回しか通らない。
DrawFormatString(150, 420, GetColor(0, 0, 0), "ファイルから項目を取得中...");
/*項目の取得*/
if (load->CheckFileDate() == -1) { break; }
dates = load->SetDatesTotalNum();
sys.SetArr(dates);//データを格納する配列の領域を確保
break;
case 1: //データを代入
load->SetFileDate(sys.PassIntDates("scene"), sys.PassIntDates("mode"), sys.PassStringDates("name"));
missed_dates = load->LoadSound(sys.PassIntDates("sound_h"));
break;
case 2: //ロードが完了した
delete load;
complete = true;
break;
case -1: //ファイルや、ファイル内に項目が見つからなかった
DrawFormatString(100, 420, GetColor(255, 0, 0), "ファイル、あるいは、データがありません。");
//5秒間メッセージを表示して、その後終了させる。
show--;
if (show == 0) {
delete load;
return 0;
}
break;
case -2: //ロードに失敗したサウンドがある。
DrawFormatString(150, 370, GetColor(175, 175, 175), "以下のファイルはロードに失敗しました。");
load->ShowLoadError1();
sys.GetMissedDatesSum(missed_dates);
load -> ShowLoadError2(sys.PassStringDates("missedsound"));
//5秒間表示させ、ロードを完了させる。
show--;
if (show == 0) { load->ShowLoadError1(true); }
break;
}
//-----変数をいじる-----//
loadstatus = load->SetLoadStatus();
flame++;
if (x == 0) { xturn = false; }
else if (x == 100) { xturn = true; }
if ((flame % 2) == 0 && xturn == false) { x+=2; }
else if (flame % 2 == 0/* && xturn == true */) { x-=2; }
}
//*****起動終了*****//
DxLib_End();
return 0;
}
Load.h
#pragma once
#include<string>
#include<vector>
using namespace std;
class LOAD{
public:
LOAD();
int SetLoadStatus(void);//ロードの過程を示す
int CheckFileDate(void);//ファイルを読み込む
int SetDatesTotalNum(void);//項目数を提示->配列の確保に使用
void SetFileDate(int* scene, int* mode, string* name);//確保された配列に代入。
int LoadSound(int* sound_h);//サウンドを読み込み、確保された配列へハンドルを渡す。
void ShowLoadError1(bool close = false); //エラーの項目を見せる(引数trueでセクションを終了)
void ShowLoadError2(string* missedsound); //エラーの項目をMSYSクラスに渡す。
private:
int loadstatus; //ロードの進行
int dates_counter; //項目数-1
vector<string>name_r; //サウンドファイルの名前
vector<int>scene_r;
vector<int>mode_r; //再生の方法
vector<int>errornum; //ロードエラーの項目の番号
};
Load.cpp
#include"Dxlib.h"
#include"Load.h"
#include<vector>
#include<string>
#include<stdlib.h>
using namespace std;
LOAD::LOAD(){
loadstatus = 0;
dates_counter = -1;
}
int LOAD::SetLoadStatus(){
return loadstatus;
}
int LOAD::CheckFileDate(){
int FileHandle;
FileHandle = FileRead_open( "SOUND LIST.txt" ) ;
if(FileHandle == -1){
loadstatus = -1;
return -1;
}
//-----読み込み-----//
char scenebuff[2];
int scene_w;
char modebuff[2];
int mode_w;
char namebuff[50];
//データのある71バイト目に移動
FileRead_seek(FileHandle, 70, SEEK_SET);
if(FileRead_eof(FileHandle) != 0){
loadstatus = -1;
return -1;
}
while(FileRead_eof(FileHandle) == 0){
/*scene*/
FileRead_read(&scenebuff, 1, FileHandle);
scene_w = strtol(scenebuff, NULL, 10);
scene_r.push_back(scene_w);
FileRead_seek(FileHandle, 1, SEEK_CUR);
/*mode*/
FileRead_read(&modebuff, 1, FileHandle);
mode_w = strtol(modebuff, NULL, 10);
mode_r.push_back(mode_w);
FileRead_seek(FileHandle, 1, SEEK_CUR);
/*name*/
FileRead_gets(namebuff, 50, FileHandle);
name_r.push_back(namebuff);
dates_counter++;
}
if (FileRead_close(FileHandle) == -1) {
return -1;
}
//完了したら
loadstatus = 1;
return 0;
}
int LOAD::SetDatesTotalNum(void){
if (dates_counter < 0) {
return 0;
}
else { return dates_counter; }
}
void LOAD::SetFileDate(int* scene, int* mode, string* name){
for(int i = 0; i <= dates_counter; i++){
name[i] = name_r[i];
mode[i] = mode_r[i];
scene[i] = scene_r[i];
}
}
int LOAD::LoadSound(int* sound_h){
string filepath = ".\\sounds\\";
string* fullpath;
bool issamename = false;
int process; //非同期読み込み中のファイル数
fullpath = new string[dates_counter];
for(int i = 0; i <= dates_counter; i++){
fullpath[i] = filepath + name_r[i];
}
//-----ハンドルゲット-----//
SetUseASyncLoadFlag(TRUE);
for(int i = 0; i <= dates_counter; i++){
/*重複をさがす*/
for(int j = i - 1; j >= 0; j--){
if(fullpath[i] == fullpath[j]){
sound_h[i] = sound_h[j];
issamename = true;
break;
}
}
/*新しい項目なら読み込む*/
if(!issamename){
sound_h[i] = LoadSoundMem(fullpath[i].c_str());
}
}
/*進捗を表示*/
process = GetASyncLoadNum();
DrawFormatString(100, 400, GetColor(100 + (process * 2), 200, 200), "...%2d / %d", process, (dates_counter + 1));
/*完了したら*/
if(process == 0){
loadstatus = 2;
delete[] fullpath;
/*エラー走査*/
for(int i = 0; i <= dates_counter; i++){
if(sound_h[i] == -1){
errornum.push_back(i);
loadstatus = -2;
}
}
}
return errornum.size();
}
void LOAD::ShowLoadError1(bool close){
DrawFormatString(40,390,GetColor(200,200,200),"TOTAL:%d",errornum.size());
for(unsigned i = 0; i <= errornum.size(); i++){
DrawFormatString(140,390+(i*20),GetColor(255,0,0),"%s",name_r[errornum[i]].c_str());
}
if(close){
//completed
loadstatus = 2;
}
}
void LOAD::ShowLoadError2(string* missedsound){
for(unsigned i = 0; i <= errornum.size(); i++){
missedsound[i] = ".\\sounds\\" + name_r[i];
}
}
mainsystem.h
class MSYS{
public:
MSYS();
~MSYS();
/*collect dates*/
void SetArr(int arr_length);//このクラスで重宝する配列を確保。
string* PassStringDates(string variablename);//要求されたstring型の配列の参照を返す
int* PassIntDates(string variablename);//要求されたint型の配列の参照を返す
void GetMissedDatesSum(int num);
/*handles and a player*/
/*Pass dates to UI class*/
private:
int* scene;
string* name;
int* mode;
int* sound_h;
string* missedsound;
bool ismissed;
};
mainsystem.cpp
#include<string>
#include"DxLib.h"
#include"mainsystem.h"
using namespace std;
MSYS::MSYS(){
ismissed = false;
}
MSYS::~MSYS(){
delete[] scene;
delete[] name;
delete[] mode;
delete[] sound_h;
if(ismissed){ delete[] missedsound; }
}
void MSYS::SetArr(int arr_length){
scene = new int[arr_length];
name = new string[arr_length];
mode = new int[arr_length];
sound_h = new int[arr_length];
}
string* MSYS::PassStringDates(string variablename){
string error[1] = {"error"};
if(variablename == "name"){
return name;
}
else if(variablename == "missedsound"){
return missedsound;
}
else{
return error;//もはや使わないけど間に合わせ
}
}
int* MSYS::PassIntDates(string variablename){
int error = -1;
if(variablename == "scene"){
return scene;
}
else if(variablename == "mode"){
return mode;
}
else if(variablename == "sound_h"){
return sound_h;
}
else{
return &error;//もはや使わないけど間に合わせ
}
}
void MSYS::GetMissedDatesSum(int num){
ismissed = true;
missedsound = new string[num];
}
また、次のエラーが出ました。
~その1~
File:c:(中略)\vc\include\xmemory0
Line:106
Expression:"(_Ptr_user&(_BIG_ALLOCATION_ALIGNMENT -1))==0"&&0
~その2~
(前略)アクセス違反が発生しました
//mwmcpy.asm
CopyUpDwordLoop:
mov edx, dword ptr [esi]
mov dword ptr [edi], edx//ココらしい
add edi, 4
add esi, 4
sub ecx, 1
jne CopyUpDwordLoop
不足した情報があれば、お知らせください。
どうぞ、よろしくお願いします。