Модераторы: Poseidon, Snowy, bems, MetalFan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Проблема с памятью, "Собственная" куча 
V
    Опции темы
creator32
Дата 5.7.2009, 16:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 3
Регистрация: 26.4.2009

Репутация: нет
Всего: нет



Здравствуйте. Если вдруг Вы знаете как решить следующую проблему, прошу - отпишитесь. 
Проблема: 
----- Нужно организовать собственный менеджер памяти на языке ObjectPascal. Это я организовал. Мне требуется в своём проекте работать с этим менеджером. А именно, я хочу работать с динамическим списком структур. 
Ниже код менеджера: 
Код

unit [HIDE];

interface

uses
  SysUtils, Graphics, ExtCtrls, StdCtrls;

type

 pRingList = ^TRingList;
 TRingList = record   //Структура, хранящая данные о свободном блоке
  Next:pRingList;     // Указатель на следующий элемент списка
  StartData:Pointer;  // Указатель на начало свободного блока
  Size:Integer;       // Размер незанятого блока
 end;

 TMemManager = class(TObject)
  PUBLIC
    constructor Create(BlockSize:Integer);
    destructor Destroy();
    procedure _GetMem(var P:Pointer ; BlockSize:Integer);
    function _FreeMem(DataPointer:Pointer; BlockSize:Integer):boolean;
  PRIVATE
    Head : pRingList;       //Голова списка
    Tail : pRingList;       //Хвост списка
    HeapStartPos : Pointer; //Указатель на начало кучи
    HeapEndPos :Pointer;    //Указатель на конец кучи
    HeapSize: Integer;
    IsEmpty : boolean;      //Если TRUE, то куча пуста
    function TakeMem(ListElem:pRingList; BlockSize:Integer):Pointer;
    procedure FreeListElem(ListElem:pRingList);
    function IsInHeap(DataPointer:Pointer):boolean;
    function DoesItFree(DataPointer:Pointer):boolean;
    procedure ShowList(Memo:TMemo);
    procedure ShowToImage(var Im:TPaintBox);
 end;

implementation

procedure TMemManager.ShowToImage(var Im:TPaintBox);
[HIDE]
end;

destructor TMemManager.Destroy();
begin
 FreeMem(HeapStartPos,HeapSize);
end;

procedure TMemManager.ShowList(Memo:TMemo);
[HIDE]
end;

constructor TMemManager.Create(BlockSize:Integer);
begin
 IsEmpty:=True;
 HeapStartPos:=SysGetMem(BlockSize);
 HeapSize:=BlockSize;
 New(Head);
 Head.StartData:=HeapStartPos;
 HeapEndPos:=pointer(integer(HeapStartPos)+BlockSize);
 Head.Size:=BlockSize;
 Tail:=Head;
 Head.Next:=Tail;
 Tail.Next:=Head;
end;

procedure TMemManager.FreeListElem(ListElem:pRingList);
var Cur:pRingList;
begin
 if not ((ListElem=Head) and (ListElem=Tail)) then
 begin
  Cur:=Head;
  while Cur.Next<>ListElem do
   Cur:=Cur.Next;
  Cur.Next:=ListElem.Next;
  FreeMem(ListElem,SizeOf(ListElem));
 end;
end;

function TMemManager.TakeMem(ListElem:pRingList; BlockSize:Integer):Pointer;
begin
 Result:=ListElem.StartData;
 Dec(ListElem.Size,BlockSize);
 if ListElem.Size=0 then FreeListElem(ListElem) else
  ListElem.StartData:=Pointer(Integer(ListElem.StartData)+BlockSize);
end;

procedure TMemManager._GetMem(var P:Pointer ; BlockSize:Integer);
var Cur:pRingList;
begin
 if not (BlockSize>HeapSize) then
 begin
  if IsEmpty then
  begin
   P:=Head.StartData;
   Dec(head.Size,BlockSize);
   Head.StartData:=Pointer(Integer(Head.StartData)+Integer(BlockSize));
   IsEmpty:=False;
  end else
  begin
   Cur:=Head;
   repeat
    if Cur.Size>=BlockSize then break;
    Cur:=Cur.Next;
   until Cur=Head;
   if Cur.Size>=BlockSize then P:=TakeMem(Cur,BlockSize) else P:=NIL;
  end;
 end else P:=NIL;
end;

function TMemManager.IsInHeap(DataPointer:Pointer):boolean;
begin
 Result:=False;
 if ((Integer(DataPointer)>=Integer(HeapStartPos)) and (Integer(DataPointer)<=Integer(HeapEndPos))) then
  Result:=True;
end;

function TMemManager.DoesItFree(DataPointer:Pointer):boolean;
var Cur:pRingList;
begin
 Result:=False;   //Участок ранее не освобождался
 Cur:=Head;
 repeat
  if ((Integer(DataPointer)>=Integer(Cur.StartData)) and (Integer(DataPointer)<Integer(Cur.StartData)+Integer(Cur.Size)))
  then begin
   Result:=True; //участок памяти ранее уже освобождался. Его не трогаем
   exit;
  end;
  cur:=cur.Next;
 until cur=head;
end;

function TMemManager._FreeMem(DataPointer:Pointer; BlockSize:Integer):boolean;
var Cur:pRingList;
begin
 Result:=True;
 cur:=head;
 if not IsInHeap(DataPointer) then Result:=False else
  if not DoesItFree(DataPointer) then
  begin
   New(Cur);
   Cur.StartData:=DataPointer;
   Cur.Size:=BlockSize;
   Tail.Next:=Cur;
   Tail:=Cur;
   Tail.Next:=Head;
  end;
end;

end.



Дальше. В этом модуле я работаю со своей "кучей". При срабатывании конструктора необходимо динамически создать две структуры класса TSnakeElem. И главное, что б они располагались в моей куче.
Тут начинается самое веселоё ))
При исполнении 
Код
MemManager._GetMem(pointer(SHead), Size);
 SHead все таки начинает ссылаться туда куда надо, а вот записи этой структуры (X,Y,Next) вообще залазят на методы MemManager. Например: TSnake.SHead.X и TMemManager.Head ссылаються на один и тот же адрес. TSnake.STail.X и MemManager.Tail тоже имеют одинаковые адреса. В чем проблема? Почему адреса X-а и Y-ка не идут после SHead? 
Код

unit My_Snake;

interface

uses  [MANAGER_MODULE], ExtCtrls, Dialogs, SysUtils;

type

 pSnakeElem = ^TSnakeElem;

 TSnakeElem = class (TObject)
  X : Integer;        // координата по х (верхняя левая точка квадратика)
  Y : Integer;        // координата по у (верхняя левая точка квадратика)
  Next : pSnakeElem;  { указатель на следующий элемент змейки.
                        Если NIL , то обрабатываемый элемент - хвост змеи }
 end;

 TSnake = class (TObject)
  SHead : pSnakeElem;
  STail : pSnakeElem;
  constructor Create();
 end;

 var MemManager : TMemManager;

implementation

constructor TSnake.Create();
var buf:pSnakeElem;
    size:Integer;
begin
 Size:=TSnakeElem.InstanceSize;
 MemManager:=TMemManager.Create(1024);
 MemManager._GetMem(pointer(SHead), Size);
 SHead.X:=20;
 SHead.Y:=20;
 MemManager._GetMem(pointer(Buf), Size);
 Buf^.X:=40;
 Buf^.Y:=20;
 SHead^.Next:=Buf;
 Buf.Next:=NIL;
end;

end.


Приложил весь проект. Очень нужна помощь

Присоединённый файл ( Кол-во скачиваний: 2 )
Присоединённый файл  Game.rar 10,72 Kb
PM MAIL   Вверх
creator32
Дата 5.7.2009, 18:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 3
Регистрация: 26.4.2009

Репутация: нет
Всего: нет



Кароче.. Так я и не понял как Delphi работает с памятью под юзеровские классы. Но проблема решилась указанием вместо  
Код
TSnakeElem = class (TObject)
 обычной записи 
Код

TSnakeElem = record
 . Теперь вот сижу и думаю: "Какая муха меня дернула описывать классом вместо того что б как по старинке рекордом все налепить ((( Пол дня в ...ОПУ (("

Это сообщение отредактировал(а) creator32 - 5.7.2009, 21:21
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0418 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.