exeが停止する原因がわからない

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
Tomo
記事: 16
登録日時: 10年前
住所: 埼玉県

exeが停止する原因がわからない

#1

投稿記事 by Tomo » 8年前

なぜ.exeが停止するのか分からないので投稿しました。
今、テキストファイルから読み込んだデータをもとに問題を出題し入力された解答に対して正誤判定を行うというプログラムを作ろうと思っています。
しかし、それ以前に起動した瞬間に.exeが停止してしまい前に進めない状態です。ソースコードのどこに原因があるのでしょうか?
デバッグしたときはscreenのNowScreenNumの値が初期化されてないような値を示していたのでそれが原因かなと思ったのですがソースコードのどこに原因があるのかわわかりませんでした。
オブジェクト指向プログラミングをしようと練習中です。添付ファイルにUMLのクラス図を載せています。
構造や実装方法でも指摘やアドバイスがあればいってください。
環境 windows10,visualstudio2015community,C++,Dxライブラリ使用

以下コードです
common.h

コード:

#pragma once
#include "DxLib.h"

#define HEIGHT 400
#define WIDTH 640
#define BITS 16
#define TITLE "WORDLEARNING"
const int Color = GetColor(255, 255, 255);
Singleton.h

コード:

#pragma once

template <typename _T>

class Singleton {
protected:
	Singleton(){}
	virtual ~Singleton(){}
	Singleton(const Singleton& r){}
	Singleton& operator=(const Singleton& r){}

public:
	static _T* Instance() {
		static _T inst;
		return &inst;
	}

};
keyboard.h

コード:

#pragma once
#include "Singleton.h"

class Keyboard:public Singleton<Keyboard>{
	Keyboard();
	friend Singleton<Keyboard>;
public:
	bool Update();
	int GetPressingCount(int KeyCode);
	int GetReleasingCount(int KeyCode);

private:
	static const int KEY_NUM = 256;
	int mKeyPressingCount[KEY_NUM];
	int mKeyReleasingCount[KEY_NUM];
	bool IsAvailableCode(int KeyCode);
};
keyboard.cpp

コード:

#include "Keyboard.h"
#include <DxLib.h>

Keyboard::Keyboard(){
	memset(mKeyPressingCount, 0, sizeof(mKeyPressingCount));
	memset(mKeyReleasingCount, 0, sizeof(mKeyReleasingCount));
}

bool Keyboard::Update(){
	char NowKeyState[KEY_NUM];
	GetHitKeyStateAll(NowKeyState);
	for (int i = 0;i < KEY_NUM;i++) {
		if (NowKeyState[i] != 0) {
			if (mKeyReleasingCount[i] > 0)mKeyReleasingCount[i] = 0;
			mKeyPressingCount[i]++;
		}
		else {
			if (mKeyPressingCount[i] > 0)mKeyPressingCount[i] = 0;
			mKeyReleasingCount[i]++;
		}
	}
	return true;
}

int Keyboard::GetPressingCount(int KeyCode){
	if (!Keyboard::IsAvailableCode(KeyCode))return -1;
	return mKeyPressingCount[KeyCode];
}

int Keyboard::GetReleasingCount(int KeyCode){
	if (!Keyboard::IsAvailableCode(KeyCode))return -1;
	return mKeyReleasingCount[KeyCode];
}

bool Keyboard::IsAvailableCode(int KeyCode){
	if (!(0 <= KeyCode&&KeyCode < KEY_NUM))return false;
	return true;
}

Title.h

コード:

#pragma once
#include "Screen.h"

class Title {

private:
	int transmittance;
	int transmitswitch;
public:
	Title();
	~Title();
	void Draw();

};
Title.cpp

コード:

#include "Title.h"
#include "Common.h"
#include <DxLib.h>

Title::Title(){
	transmitswitch = 0;
	transmittance = 100;
}

void Title::Draw(){
	switch (transmitswitch){
	case 0:
		transmittance += 2;
		if (transmittance >= 255)transmitswitch++;
		break;
	case 1:
		transmittance -= 2;
		if (transmittance <= 80)transmitswitch--;
		break;
	}
	DrawString(180, 180, "WORD LEARNING", Color);
	SetDrawBlendMode(DX_BLENDMODE_ALPHA, transmittance);
	DrawString(180, 300, "Press Enter to start", Color);
	SetDrawBlendMode(DX_BLENDMODE_NOBLEND, 0);
}

Title::~Title(){
	
}
ScreenTransition.h

コード:

#pragma once
#include "Screen.h"
#include "Title.h"

class ScreenTransition{

protected:
	int NowScreenNum;
	bool active;

public:
	ScreenTransition();
	~ScreenTransition();
	virtual void Transition() = 0;
	bool GetActiveFlag();
};
ScreenTransition.cpp

コード:

#include "ScreenTransition.h"

ScreenTransition::ScreenTransition(){
}

bool ScreenTransition::GetActiveFlag() {
	return active;
}

ScreenTransition::~ScreenTransition() {
}

TitleScreen.h

コード:

#pragma once
#include "ScreenTransition.h"

class TitleScreen:public ScreenTransition{
private:
	Title* title;
	
public:
	TitleScreen();
	~TitleScreen();
	void Transition();

};

TitleScreen.cpp

コード:

#include "TitleScreen.h"
#include "Keyboard.h"
#include "DxLib.h"
#include "Common.h"

TitleScreen::TitleScreen(){
	NowScreenNum = 0;
	active = true;
	title = new Title;
}

void TitleScreen::Transition(){
	switch (NowScreenNum){
	case 0:
		title->Draw();
		break;
	case 1:
		active = false;
		break;
	default:
		DrawFormatString(320, 150, Color, "%d", NowScreenNum);
		break;
	}
	if (Keyboard::Instance()->GetPressingCount(KEY_INPUT_RETURN) == 1)NowScreenNum++;
}



TitleScreen::~TitleScreen(){
	delete title;
}

StateTransition.h

コード:

#pragma once
#include "ScreenTransition.h"

class StateTransition{
private:
	int NowStateNum;
	int BackScreenGh;
	ScreenTransition* screen[4];
public:
	StateTransition();
	~StateTransition();
	void Draw();
	void Transition();

};

StateTransition.cpp

コード:

#include "StateTransition.h"
#include "Common.h"//完成後必要ない
#include "Keyboard.h"
#include "DxLib.h"

#include "TitleScreen.h"

StateTransition::StateTransition(){
	NowStateNum = 0;
	BackScreenGh= LoadGraph("Graph/backscreen.png");//640*400
	TitleScreen titleS;
	screen[0] = &titleS;
}

void StateTransition::Draw(){
	DrawGraph(0, 0, BackScreenGh, TRUE);
}

void StateTransition::Transition() {
	while (!ScreenFlip() && !ProcessMessage() && !ClearDrawScreen()) {
		Keyboard::Instance()->Update();
		Draw();
		switch (NowStateNum) {
		case 0:
			screen[0]->Transition();
			if(screen[0]->GetActiveFlag())NowStateNum++;
			break;
		case 1:
			DrawFormatString(320, 150, Color, "%d", NowStateNum);
			break;
		}
		//if (Keyboard::Instance()->GetPressingCount(KEY_INPUT_RETURN) == 1)NowStateNum++;
		if (Keyboard::Instance()->GetPressingCount(KEY_INPUT_ESCAPE) != 0)break;
	}
}

StateTransition::~StateTransition(){
}

main.cpp

コード:

#include <DxLib.h>
#include "Common.h"
#include "StateTransition.h"

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
	SetGraphMode(WIDTH, HEIGHT, BITS);
	SetMainWindowText(TITLE);
	ChangeWindowMode(TRUE);
	DxLib_Init();
	SetDrawScreen(DX_SCREEN_BACK);
	SetAlwaysRunFlag(TRUE);
	ChangeFont("游明朝");

	StateTransition* st;
	st = new StateTransition;
	st->Transition();
	

	DxLib_End();
	return 0;
}
添付ファイル
クラス図.png
作ろうとしているプログラムの構造です。

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

Re: exeが停止する原因がわからない

#2

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

とりあえず、StateTransition::StateTransition関数の静的でないローカル変数titleSはこの関数を抜けた時点で消滅するので、
ポインタを用いてStateTransition::Transition関数(など)からそれにアクセスしようとしてはいけません。
十分な期間消えないように、titleSをStateTransitionのメンバ変数にするといいかもしれません。
オフトピック
どうしてわざわざWinMain関数内でStateTransitionオブジェクトを動的確保して、しかもdeleteしていないのでしょうか?
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

Tomo
記事: 16
登録日時: 10年前
住所: 埼玉県

Re: exeが停止する原因がわからない

#3

投稿記事 by Tomo » 8年前

みけCATさんありがとうございます。titleSをStateTransitionのメンバ変数にしたら解決しました。
1つお聞きしたいのですが
みけCAT さんが書きました:
オフトピック
どうしてわざわざWinMain関数内でStateTransitionオブジェクトを動的確保して、しかもdeleteしていないのでしょうか?
deleteは忘れていたので追加しました。動的に確保したのにdeleteしないのはいけないですね。
しかし上記の文だとWinMain関数内でStateTransitionオブジェクトを動的確保こと自体が悪いように思えるののですが実際よくないのですか?

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

Re: exeが停止する原因がわからない

#4

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

蜜柑 さんが書きました:しかし上記の文だとWinMain関数内でStateTransitionオブジェクトを動的確保こと自体が悪いように思えるののですが実際よくないのですか?
この場合、全く動的確保する必要性を感じないのにわざわざ動的確保しているのが個人的に変だと思いました。
この先StateTransitionクラスのメンバとしてスタックに入らないような数MB程度の配列を追加するような場合は、動的確保しないといけなくなるかもしれません。
StateTransitionクラスのデストラクタでDXライブラリの機能を使った終了処理をするなら、

コード:

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
	SetGraphMode(WIDTH, HEIGHT, BITS);
	SetMainWindowText(TITLE);
	ChangeWindowMode(TRUE);
	DxLib_Init();
	SetDrawScreen(DX_SCREEN_BACK);
	SetAlwaysRunFlag(TRUE);
	ChangeFont("游明朝");

	{
		StateTransition st;
		st.Transition();
	}

	DxLib_End();
	return 0;
}
のようにブロックを追加してDxLib_End()の前にデストラクタが呼ばれるようにするといいでしょう。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

Tomo
記事: 16
登録日時: 10年前
住所: 埼玉県

Re: exeが停止する原因がわからない

#5

投稿記事 by Tomo » 8年前

みけCATさんありがとうございます。
今まではいつでもどこでも動的確保していたのでこれからは場合に応じて使い分けていきたいと思います。

閉鎖

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