大きなメモリ確保の順番
Posted: 2012年10月06日(土) 15:15
TaskListクラスはコンストラクタ(int m, int n)でnew char[m*(n+2)]のようにm(n+2)バイトのメモリを確保する、
シューティングゲームで頻繁に敵や弾を出したり消したりすることによって、
メモリの断片化を防ぐ目的のクラスです。
リストの各領域にはTaskクラスが作られ、全ての移動物体はTaskクラスから継承されます。
詳細なコードTask.cppは一番下に貼りました。
これを使い、この順番で確保するとエラーが出ず、
この順番で確保するとエラーが出ます。
list1~list5はグローバル変数です
エラー
HEAP[001_control.exe]: HEAP: Free Heap block ad35f8 modified at ad3664 after it was freed
Windows によって 001_control.exe でブレークポイントが発生しました。
ヒープが壊れていることが原因として考えられます。001_control.exe または読み込まれた DLL にバグがあります。
あるいは、001_control.exe がフォーカスを持っているときに、ユーザーが F12 キーを押したことが原因として考えられます。
可能であれば、出力ウィンドウに詳細な診断情報が表示されます。
【質問】
「メモリのある領域を重複して解放している」とOSが言っていると思うのですが、
何故そのようなエラーが出るのでしょうか?
また、なぜ順番に依るのでしょうか?
Task.cpp↓
シューティングゲームで頻繁に敵や弾を出したり消したりすることによって、
メモリの断片化を防ぐ目的のクラスです。
リストの各領域にはTaskクラスが作られ、全ての移動物体はTaskクラスから継承されます。
詳細なコードTask.cppは一番下に貼りました。
これを使い、この順番で確保するとエラーが出ず、
list1=new TaskList(128, 64);
list2=new TaskList(128, 2048);
list3=new TaskList(128, 256);
list4=new TaskList(128, 256);
list5=new TaskList(128, 2);list5=new TaskList(128, 2);
list2=new TaskList(128, 64);
list3=new TaskList(128, 2048);
list4=new TaskList(128, 256);
list1=new TaskList(128, 256);エラー
HEAP[001_control.exe]: HEAP: Free Heap block ad35f8 modified at ad3664 after it was freed
Windows によって 001_control.exe でブレークポイントが発生しました。
ヒープが壊れていることが原因として考えられます。001_control.exe または読み込まれた DLL にバグがあります。
あるいは、001_control.exe がフォーカスを持っているときに、ユーザーが F12 キーを押したことが原因として考えられます。
可能であれば、出力ウィンドウに詳細な診断情報が表示されます。
【質問】
「メモリのある領域を重複して解放している」とOSが言っていると思うのですが、
何故そのようなエラーが出るのでしょうか?
また、なぜ順番に依るのでしょうか?
Task.cpp↓
#include "Task.h"
#include <cassert>
//各タスクは構造体のように前後のタスクへのポインタをメンバに持っている
//リストはアクティブタスクヘッダー、フリータスクヘッダーという、ゲームの処理には直接使われない2つのタスクを持つ
//アクティブタスクヘッダーからつながるタスクがアクティブタスク(使用中のメモリ領域)であり、
//フリータスクヘッダーからつながるタスクがフリータスク(未使用のメモリ領域)である
//削除、挿入も構造体同様に行う
//i番目のタスクを取得
Task* TaskList::GetTask(size_t i)
{
return (Task*)(Buffer+TaskSize*i);
}
//タスクリストのコンストラクタ
TaskList::TaskList(size_t size, size_t num)
: TaskSize(size), TaskNum(num)
{
//最大タスクサイズはタスク数*2
Buffer=new char[TaskNum*(TaskSize+2)];
//アクティブタスクリストの初期化
//最初はヘッダーだけ
ActiveTaskHeader=GetTask(0);
ActiveTaskHeader->prev = ActiveTaskHeader->next = ActiveTaskHeader;
//フリータスクリストの初期化
//最初はヘッダーだけ
FreeTaskHeader=GetTask(1);
for(size_t i=1; i<TaskNum+2; i++)
{
GetTask(i)->prev = 0;
GetTask(i)->next = GetTask(i+1);
}
GetTask(TaskNum+1)->next = FreeTaskHeader;
}
//タスクリストにメモリを確保
//sizeはタスクからあふれないか判定するためだけ使う
void* TaskList::New(size_t size)
{
//タスクのサイズが最大サイズを超えていればエラー
assert(size<=TaskSize);
//フリータスクが1個もないときはNULLを返す
if(FreeTaskHeader->next==FreeTaskHeader)
return 0;
//フリータスクの先頭からタスクを1個取り出す
Task* task=FreeTaskHeader->next;
FreeTaskHeader->next = task->next;
return task;
}
//タスクのコンストラクタ
//listに新しいタスクを追加
Task::Task(TaskList* list)
{
//タスクをアクティブタスクリストの末尾に挿入する
prev = list->ActiveTaskHeader->prev;
next = list->ActiveTaskHeader;
prev->next = next->prev=this;
}
//タスクのデストラクタ
Task::~Task()
{
//タスクをアクティブタスクリストから取りだす
prev->next=next;
next->prev=prev;
}
//タスクを削除
void TaskList::Delete(void *p)
{
//フリータスクを解放してないか?
Task* task=(Task*)p;
assert(task->prev!=0);
//タスクをフリータスクの先頭に挿入
task->prev = 0;
task->next = FreeTaskHeader->next;
FreeTaskHeader->next = task;
}
TaskIter::TaskIter(TaskList* _list)
:list(_list), task(_list->ActiveTaskHeader)
{}
bool TaskIter::hasNext() {
return task->next!=list->ActiveTaskHeader;
}
Task* TaskIter::next() {
return task=task->next;
}
void TaskIter::remove() {
task=task->prev;
delete task->next;
}