こんにちは、rozeoです。
DXライブラリでプログラムを作って実行したところ以下のエラーダイアログが表示されました。
Debug Assertion Failed!
Program:...Documents/Visual Studio 2010/Projects/TankPlace/TankPlace.exe
File: f:/dd\vctools\crt_bld\self_x86\crt\src\dbgheap.c
Line: 1322
Exception: _CtrIsValidHeapPointer(pUserData)
For infomation on your program can cause an assertion
failure,see the Visual C++ documentation on asserts.
(Press Retry to debug applcation)
一応自分で解釈してみたところ、VC関連のファイル、dbgheap.cのヒープという部分(?)壊れているらしいです。
このヒープとはいったいなんでしょうか?
またこのエラーの原因と考えられることとはいったいなんでしょうか?
また解決するにはどのようにコードを改変すればいいでしょうか?
ご鞭撻よろしくお願いします。
突然のExceptionエラー
Re: 突然のExceptionエラー
追記
wikipediaではヒープ(領域)に関して以下のように説明されていました。
ヒープ領域(ヒープりょういき)とはコンピュータープログラミングにおいて、動的に確保可能なメモリの領域。ヒープ (heap) とは、『山積み』という言葉の中の『山』をさす英単語である。データ構造のヒープとは直接的な関係は無い。
ヒープ領域は、2種類のラベルを持つ双方向リストによって構成されている。初期状態では、リストはひとつの「未使用」ノードが全体を占めていて、メモリ確保関数(C言語のmalloc, C++のnew等)によって、「未使用」ノードから必要な分を切り取って「使用中」ノードと「未使用」ノードに分ける。確保したメモリが不要になった場合には、メモリ解放関数(C言語のfree, C++のdelete等)によってノードのラベルを「未使用」に書き換える。解放のつど、あるいはカウンタによって一定水準に達した時、連続した個々の「未使用」ノードが結合され、大きな「未使用」ノードに還元される。「未使用」ノードが不足した場合には、オペレーティングシステムに領域拡大を要求し、ヒープ領域が拡大される。 ヒープ領域により、変数領域を動的に確保できる利点があるが、領域の確保と解放の繰り返しによりヒープ上にどこからも参照されない領域が発生することがある。この領域をガベージ(ゴミ)という。 「未使用ノード」と「使用中」ノードが混在、つまりガベージによりヒープ領域がバラバラに分断された状態をフラグメンテーション状態と呼ぶ。
プログラム中にfreeは使いましたがfreeを使っコンパイルした時にはエラーは発生しませんでした。
またコンパイルエラーやワーニングは出ませんでした。
wikipediaではヒープ(領域)に関して以下のように説明されていました。
ヒープ領域(ヒープりょういき)とはコンピュータープログラミングにおいて、動的に確保可能なメモリの領域。ヒープ (heap) とは、『山積み』という言葉の中の『山』をさす英単語である。データ構造のヒープとは直接的な関係は無い。
ヒープ領域は、2種類のラベルを持つ双方向リストによって構成されている。初期状態では、リストはひとつの「未使用」ノードが全体を占めていて、メモリ確保関数(C言語のmalloc, C++のnew等)によって、「未使用」ノードから必要な分を切り取って「使用中」ノードと「未使用」ノードに分ける。確保したメモリが不要になった場合には、メモリ解放関数(C言語のfree, C++のdelete等)によってノードのラベルを「未使用」に書き換える。解放のつど、あるいはカウンタによって一定水準に達した時、連続した個々の「未使用」ノードが結合され、大きな「未使用」ノードに還元される。「未使用」ノードが不足した場合には、オペレーティングシステムに領域拡大を要求し、ヒープ領域が拡大される。 ヒープ領域により、変数領域を動的に確保できる利点があるが、領域の確保と解放の繰り返しによりヒープ上にどこからも参照されない領域が発生することがある。この領域をガベージ(ゴミ)という。 「未使用ノード」と「使用中」ノードが混在、つまりガベージによりヒープ領域がバラバラに分断された状態をフラグメンテーション状態と呼ぶ。
プログラム中にfreeは使いましたがfreeを使っコンパイルした時にはエラーは発生しませんでした。
またコンパイルエラーやワーニングは出ませんでした。
Re: 突然のExceptionエラー
ヒープ破壊はコンパイル時には検出できません。実行してはじめてエラーが発生します。
配列の範囲外アクセスや、無効なポインタ(freeしたあとのアドレス)への書き込みなどを行うとヒープが破壊されます。
具体的にどこが問題なのかはソースコードを見ないと分かりません。
配列の範囲外アクセスや、無効なポインタ(freeしたあとのアドレス)への書き込みなどを行うとヒープが破壊されます。
具体的にどこが問題なのかはソースコードを見ないと分かりません。
Re: 突然のExceptionエラー
Debugビルドして動かしても同じ状況が出るのであれば
ステップ実行等で,どの時点で例外発生しているのかを突き止めると良いでしょう.
例えば,「A()という関数を呼びだしたらそうなる」とかいうあたりまでわかれば
その関数に渡している引数の値を疑う等して,原因が究明できると思います.
Releaseだと出るけどDebugだと出ない とかいう状況だと
詳細な場所まで突き止めるのが難しくなるかもしれませんが,
それでも Releaseビルドしたものをデバッグ実行して ある程度範囲を絞りこめると思います.
ステップ実行等で,どの時点で例外発生しているのかを突き止めると良いでしょう.
例えば,「A()という関数を呼びだしたらそうなる」とかいうあたりまでわかれば
その関数に渡している引数の値を疑う等して,原因が究明できると思います.
Releaseだと出るけどDebugだと出ない とかいう状況だと
詳細な場所まで突き止めるのが難しくなるかもしれませんが,
それでも Releaseビルドしたものをデバッグ実行して ある程度範囲を絞りこめると思います.
Re: 突然のExceptionエラー
ご返事ありがとうございます。詳細なエラー発生タイミングはメインループからでてDxLib_End()までの間です。その間にはメモリ開放としてfreeだったりを記述しています。その後ににはDxLib_end()しかありません。またfreeを書いて実行した辞典ではエラーは発生しませんでした。usao さんが書きました:Debugビルドして動かしても同じ状況が出るのであれば
ステップ実行等で,どの時点で例外発生しているのかを突き止めると良いでしょう.
例えば,「A()という関数を呼びだしたらそうなる」とかいうあたりまでわかれば
その関数に渡している引数の値を疑う等して,原因が究明できると思います.
Releaseだと出るけどDebugだと出ない とかいう状況だと
詳細な場所まで突き止めるのが難しくなるかもしれませんが,
それでも Releaseビルドしたものをデバッグ実行して ある程度範囲を絞りこめると思います.
ソースコードをのせます
//main.cpp
#include "Key.h"
#include "Define.h"
int programEndFlg = FLG_OFF;
extern void KeyCheckAll();
extern void Initialization();
extern void Menu();
extern void Destract();
int ProcessLoop(){
if(ProcessMessage() != 0){
return -1;
}
if(ClearDrawScreen() != 0){
return -1;
}
KeyCheckAll();
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdShow,int nCmdLine){
SetGraphMode(750,650,32);
if(DxLib_Init() != 0 || SetDrawScreen(DX_SCREEN_BACK) != 0){
return -1;
}
Initialization();
while(ProcessLoop() == 0){
Menu();
if(CheckStateKey(KEY_INPUT_ESCAPE) != 0) break;
if(programEndFlg == FLG_ON) break;
ScreenFlip();
}
Destract();
DxLib_End();
return 0;
}
//GraphHandle.h
extern int hMenuBack;
//ColorAndFontHandle.h
extern int hWhite,hBlack,hRime,hIndigo,hBlueGreen;
extern int font_ArialBlackSize16,font_ArialBlackSize32,font_ArialBlackSize64;
//Define.h
#include "DxLib.h"
#define FLG_OFF 0
#define FLG_ON 1
#define MENUTAG 5//メニュー項目数
#define COLORWHITE GetColor(255,255,255);//色作成マクロ 白
#define COLORBLACK GetColor(0 ,0 ,0 );//色作成マクロ 黒
#include "Define.h"
#include "ColorAndFontHandle.h"
#include "GraphHandle.h"
char menuTag[MENUTAG][10] = {"newgame","continue","password","config","exit"};
int xPosSetting[MENUTAG] = {5,0,0,50,70};//中央整頓用
int menuTagPosX[MENUTAG] = {75,275,475,175,375};
int menuTagPosY[MENUTAG] = {500,500,500,550,550};
int tagMove[MENUTAG] = {1000,1200,1400,1100,1300};
int backStelseFlg = FLG_ON;
int alpha = 0;
int menuStartActiveFlg = FLG_ON;
void DrawMenu();
void MenuStart();
void Menu(){
if(menuStartActiveFlg == FLG_ON) MenuStart();
else DrawMenu();
}
void MenuStart(){
if(backStelseFlg == FLG_ON){
SetDrawBlendMode(DX_BLENDMODE_ALPHA,alpha);
DrawGraph(0,0,hMenuBack,TRUE);
SetDrawBlendMode(DX_BLENDMODE_NOBLEND,0);
alpha +=3;
if(alpha > 255){
backStelseFlg = FLG_OFF;
}
}else if(backStelseFlg == FLG_OFF){
DrawGraph(0,0,hMenuBack,TRUE);
for(int i = 0;i < MENUTAG;i++){
DrawStringToHandle(menuTagPosX[i]+xPosSetting[i],menuTagPosY[i],menuTag[i],
hBlueGreen,font_ArialBlackSize32);
}
for(int i = 0;i < MENUTAG;i++){
tagMove[i] -=25;
}
if(tagMove[0] < 75){
menuStartActiveFlg = FLG_OFF;
}
}
}
void DrawMenu(){
DrawGraph(0,0,hMenuBack,TRUE);
for(int i = 0;i < MENUTAG;i++){
DrawStringToHandle(menuTagPosX[i]+xPosSetting[i],menuTagPosY[i],menuTag[i],
hBlueGreen,font_ArialBlackSize32);
}
}
//Destract.cpp
#include "DxLib.h"
#include "ColorAndFontHandle.h"
#include "GraphHandle.h"
void Destract(){
DeleteFontToHandle(font_ArialBlackSize16);
DeleteFontToHandle(font_ArialBlackSize32);
DeleteFontToHandle(font_ArialBlackSize64);
InitGraph();
free(&hMenuBack);
free(&hWhite);
free(&hBlack);
free(&hRime);
free(&hIndigo);
free(&hBlueGreen);
}
//Initialization.cpp
#include "DxLib.h"
int font_ArialBlackSize32,font_ArialBlackSize64,font_ArialBlackSize16;
int hWhite,hBlack,hRime,hIndigo,hBlueGreen;
int hMenuBack;
void Initialization(){//変数、ハンドルなどの初期化
//既存フォント[Arial Black]のサイズ16,32,64のフォントを作成
font_ArialBlackSize16 = CreateFontToHandle("Arial Black",16,
DX_FONTTYPE_ANTIALIASING_EDGE_8X8);
font_ArialBlackSize32 = CreateFontToHandle("Arial Black",32,
DX_FONTTYPE_ANTIALIASING_EDGE_8X8);
font_ArialBlackSize64 = CreateFontToHandle("Arial Black",64,
DX_FONTTYPE_ANTIALIASING_EDGE_8X8);
hWhite = GetColor(255,255,255);//黒
hBlack = GetColor(0 ,0 ,0 );//白
hRime = GetColor(153,204,0 );//ライム
hIndigo = GetColor(51 ,51 ,153);//インディゴ
hBlueGreen = GetColor(0 ,128,128);//青緑
hMenuBack = LoadGraph("dat/MenuBack.png");
}
Re: 突然のExceptionエラー
freeしてよいのはmallocで確保した領域だけです。静的記憶領域をfreeしてはいけません。
このプログラムでは動的確保をしていないのでfreeは不要です。
スポイラーは
このプログラムでは動的確保をしていないのでfreeは不要です。
スポイラーは
► スポイラーを表示
Re: 突然のExceptionエラー
ありがとうございます。
Destract.cppのfree()のやつを全て消したらエラーが発生しました。
free関数の使い方を見誤ってました。
ご返答ありがとうございました。
Destract.cppのfree()のやつを全て消したらエラーが発生しました。
free関数の使い方を見誤ってました。
ご返答ありがとうございました。