ページ 11

ヒープ破壊の原因がわからず困っています。

Posted: 2014年10月11日(土) 21:26
by いもかん
タイトルの通り、DXライブラリを用いたゲームの制作中に遭遇したバグの原因がわかりません。
開発環境
OS:Windows7 32bit
コンパイラ:Microsoft Visual Studio 2010

プログラミングの経験は半年ほどです。

このプログラムは実行するとゲームのタイトル画面が現れます。
タイトル画面が表示されてすぐ終了すると正常終了になるのですが、タイトル画面でGAMESTARTを選んでゲーム画面に入ってから終了すると、以下のエラーメッセージが表示されます。


Windows によって DxLib_string.exe でブレークポイントが発生しました。

ヒープが壊れていることが原因として考えられます。DxLib_string.exe または読み込まれた DLL にバグがあります。

あるいは、DxLib_string.exe がフォーカスを持っているときに、ユーザーがF12 キーを押したことが原因として考えられます。

可能であれば、出力ウィンドウに詳細な診断情報が表示されます。


ゲーム画面に入らず終了した時はエラーは表示されなかったので、Scene_Menu.cpp内のEnemyMgr_Init();をコメントアウトしてみました。すると、今度はエラーメッセージが表示されなくなったので、私はEnemyMgr_Init()関数に原因があると考えています。
しかし、EnemyMgr_Init()関数や、それが書かれたEnemyMgr.cppなどのファイルを調べてみましたが、全く見当がつきません。

ファイルの数が多いので私が怪しいと思っているコードだけを貼っておきます。

情報が不足している、または文章がわかりづらいといった事があれば補足します。

main.cpp

コード:

#include"DxLib.h"
#include"KeyboardInput.h"
#include"SceneMgr.h"
#include"ExitMgr.h"
#include"Scene_Menu.h"
#include"PlayerMgr.h"
#include"Scene_Game.h"
#include"Scene_Pause.h"
#include"PlayerShotMgr.h"
#include"EnemyMgr.h"
#include"EnemyShotMgr.h"

int WINAPI WinMain( HINSTANCE hInstance , HINSTANCE hPrevInstance ,
	LPSTR lpCmdLine , int nCmdShow ){
		


		ChangeWindowMode(TRUE);

		if( DxLib_Init() == -1 ){
			exit( EXIT_FAILURE );
		}

		SetDrawScreen( DX_SCREEN_BACK );

		
		PlayerMgr_Load();

		PlayerShotMgr_Load();

		EnemyMgr_Load();

EnemyShotMgr_Load();

		//メインループ
		while( ProcessMessage() == 0 && ScreenFlip() == 0 && ClearDrawScreen() == 0 ){
			
			KeyboardMgr();

			switch( GetScene() ){
			case eScene_Menu:
				Menu();
				break;
			case eScene_Gamestart:
				
				if( Game_GetInitFlag() == 1 ){
					Game_Init();
					Game_SetInitFlag( 0 );
				}

				Game();
				break;
			case eScene_Quit:
				ReserveExit();
				break;
			case eScene_Pause:
				Pause();
				break;
			}


			
			if( GetExitFlag() == 1 ){
				break;
			}
			

			WaitTimer(16);

		}


//メモリ解放など
		PlayerMgr_End();
		PlayerShotMgr_End();
		EnemyMgr_End();
EnemyShotMgr_End();
		DxLib_End();

		return 0;
}
Scene_Game.cpp

コード:

#include"DxLib.h"
#include"Scene_Game.h"
#include"PlayerMgr.h"
#include"KeyboardInput.h"
#include"SceneMgr.h"
#include"PlayerMgr.h"
#include"PlayerShotMgr.h"
#include"EnemyMgr.h"
#include"EnemyShotMgr.h"

static int m_init_flag = 1;

void Game_Init(){

	PlayerMgr_Init();

	PlayerShotMgr_Init();

	EnemyMgr_Init();
	//ヒープ破壊の原因?

//EnemyShotMgr_Init();
//EnemyMgr_Init()を改変して作ったのでこちらでもヒープ破壊が起こる?

	return;

}

void Game(){

	if( GetKeyStateBuf( KEY_INPUT_P ) == 1 ){
		UpdateScene( eScene_Pause );
	}

	PlayerMgr_Update();

	PlayerShotMgr_Update();

	//未作成
//EnemyMgr_Update();
//EnemyShotMgr_Update();

	PlayerMgr_Draw();

	PlayerShotMgr_Draw();

	EnemyMgr_Draw();

	return;
}

void Game_SetInitFlag( int iFlag ){

	m_init_flag = iFlag;

	return;
}

int Game_GetInitFlag(){

	return m_init_flag;
}
EnemyMgr.cpp

コード:

#include"DxLib.h"
#include"EnemyMgr.h"
#include"Typedef_HitCheck.h"
#include<stdlib.h>

static int m_enemyVariety;
static enemyData_t * m_data;
static enemy_t ** m_enemy;
static position_t ** m_position;

void EnemyMgr_Load(){

	int i , k;

	m_enemyVariety = 1;

	m_data = ( enemyData_t * ) malloc( sizeof( enemyData_t ) * m_enemyVariety );

	m_enemy = ( enemy_t ** ) malloc( sizeof( enemy_t * ) * m_enemyVariety );
	
	m_position = ( position_t ** ) malloc( sizeof( position_t * ) * m_enemyVariety );

	if( ( m_data == NULL ) ||
		( m_enemy == NULL ) ||
		( m_position == NULL ) ){

			DxLib_End();
			exit( EXIT_FAILURE );
	}

	EnemyMgr_LoadData();
	
	
	for( i = 0 ; i < m_enemyVariety ; i++ ){
		
		m_enemy[i] = ( enemy_t * ) malloc( sizeof( enemy_t * ) * m_data[i].max );
		
		m_position[i] = ( position_t * ) malloc( sizeof( position_t * ) * m_data[i].max );
		if( ( m_enemy[i] == NULL ) ||
			( m_position[i] == NULL ) ){

				DxLib_End();
				exit( EXIT_FAILURE );
		}

	}

	return;
}

void EnemyMgr_LoadGraph(){

	int i;

	for( i = 0 ; i < m_enemyVariety ; i++ ){

		LoadDivGraph( "images/testE.png" , m_data[i].graphNum , m_data[i].graphNumX , m_data[i].graphNumY
				, m_data[i].graphSizeX , m_data[i].graphSizeY , m_data[i].graph );

	}


	return;
}

void EnemyMgr_LoadData(){

	int i;

	for( i = 0 ; i < m_enemyVariety ; i++ ){

		m_data[i].hit = ( hitData_t * ) malloc( sizeof( hitData_t ) );
		m_data[i].hit->type = RECTANGLE;
		m_data[i].hit->area.rect.start.x = 0;
		m_data[i].hit->area.rect.start.y = 0;
		m_data[i].hit->area.rect.width = 192;
		m_data[i].hit->area.rect.height = 128;

		m_data[i].graphNum = 2;
		m_data[i].graphNumX = 1;
		m_data[i].graphNumY = 2;
		m_data[i].graphSizeX = 192;
		m_data[i].graphSizeY = 128;

		m_data[i].max = 2;
		m_data[i].maxhp = 4;

		m_data[i].graph = ( int * ) malloc( sizeof( int ) * m_data[i].graphNum );
		
		if( m_data[i].graph == NULL ){

			DxLib_End();
			exit( EXIT_FAILURE );
		}


	}

	EnemyMgr_LoadGraph();

	return;
}

void EnemyMgr_Init(){
	int i , k;

	for( i = 0 ; i < m_enemyVariety ; i++ ){
		for( k = 0 ; k < m_data[i].max ; k++ ){
			m_position[i][k].x = k * 200;
			m_position[i][k].y = 0;
			m_enemy[i][k].flag = 1;
			m_enemy[i][k].currentgraph = 0;
			m_enemy[i][k].hp = m_data[i].maxhp;
			m_enemy[i][k].state = 0;
		}

	}
	

	return;
}

void EnemyMgr_Update();

void EnemyMgr_Draw(){
	
	int i , k;
	for( i = 0 ; i < m_enemyVariety ; i++ ){
		for( k = 0 ; k < m_data[i].max ; k++ ){

			if( m_enemy[i][k].flag == 1 ){

				DrawGraph( m_position[i][k].x, m_position[i][k].y 
					, m_data[i].graph[m_enemy[i][k].currentgraph] , TRUE );

			}

		}
	}


	return;
}

void EnemyMgr_End(){

	int i;
	
	for( i = 0 ; i < m_enemyVariety ; i++ ){
	
		if( m_data[i].graph != NULL ){
			free( m_data[i].graph );
			m_data[i].graph = NULL;
		}
		if( m_data[i].hit != NULL ){
			free( m_data[i].hit );
			m_data[i].hit = NULL;
		}
		if( m_enemy[i] != NULL ){
			free( m_enemy[i] );
			m_enemy[i] = NULL;
		}
		if( m_position[i] != NULL ){
			free( m_position[i] );
			m_position[i] = NULL;
		}

	}
	
	if( m_data != NULL ){
		free( m_data );
		m_data = NULL;
	}
	if( m_enemy != NULL ){
		free( m_enemy );
		m_enemy = NULL;
	}
	if( m_position != NULL ){
		free( m_position );
		m_position = NULL;
	}

	return;
}
EnemyMgr.h

コード:

#ifndef DEF_ENEMYMGR_H

#define DEF_ENEMYMGR_H

struct hitData;
struct position;

typedef struct{
	struct hitData * hit;
	int graphNum , graphNumX , graphNumY;
	int graphSizeX , graphSizeY;
	int *graph;
	int maxhp;
	int max;
}enemyData_t;

typedef struct{
	int currentgraph;
	int flag;
	int hp;
	int state;
}enemy_t;



void EnemyMgr_Load();

void EnemyMgr_LoadData();

void EnemyMgr_LoadGraph();

void EnemyMgr_Init();

void EnemyMgr_Update();

void EnemyMgr_Draw();

void EnemyMgr_End();

#endif
Typedef_HitCheck.h

コード:

#ifndef TYPEDEF_HITCHECK_H

#define TYPEDEF_HITCHECK_H

typedef struct position{
	float x;
	float y;
}position_t;

typedef position_t vector_t;

typedef struct rectangle{
	position_t start;
	int width;
	int height;
}rectangle_t;

typedef struct circle{
	position_t center;
	int radius;
}circle_t;

typedef union hitArea{
	rectangle_t rect;
	circle_t circ;
}hitArea_t;

typedef enum hitType{
	RECTANGLE,
	CIRCLE,
}hitType_t;

typedef struct hitData{
	hitType_t type;
	hitArea_t area;
}hitData_t;

#endif

Re: ヒープ破壊の原因がわからず困っています。

Posted: 2014年10月11日(土) 22:45
by jay
それじゃあブレークポイントを仕込んで
EnemyMgr_Init()をステップ実行してみると原因が分かるかもしれません。

Re: ヒープ破壊の原因がわからず困っています。

Posted: 2014年10月12日(日) 00:25
by いもかん
jayさん、返信ありがとうございます。おかげさまで原因を突き止めることができました。

EnemyMgr_Init()にブレークポイントを仕込んでも何も起きませんでしたが、EnemyMgr_End()にブレークポイントを仕込んだら、Enemyを開放したところでエラーメッセージが表示されました。

EnemyMgr_Load()関数内で確保したメモリのサイズが間違っていたことが原因だったようです。

もとのコードでは

m_enemy = ( enemy_t * ) malloc( sizeof( enemy_t * ) * m_data.max );

となっていましたが、正しくは

m_enemy = ( enemy_t * ) malloc( sizeof( enemy_t ) * m_data.max );

と書かなければなりませんでした。また、m_positionにアドレスを格納したメモリのサイズも同じように間違っていました。