Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Форум «Всё о Паскале» _ Задачи _ Freemem

Автор: ангел 30.11.2006 6:17

Ошибка у меня возникает при вызове этой процедуры...
Либо указатель пустой или число освобождамых байтов выходит за границы кучи ???
вот код:


procedure Push(E:ElementType;var S:Stack);
var
P:pStackElem;
begin
P:=new(pStackElem);
GetMem(P^.Elem,SizeOf(ElementType));
Move(E,P^.Elem,SizeOf(ElementType));
P^.Next:=S.Top;
S.Top:=P;
S.Size:=S.Size+Sizeof(ElementType)+SizeOf(pStackElem)*2+SizeOf(Pointer);
end;

procedure Pop(S:Stack;var E:ElementType);
var top:pStackElem;
begin
if S.Top<>nil then
begin
Move(S.Top^.Elem,E,SizeOf(ElementType));
top:=S.Top^.Next;
FreeMem(S.Top^.Elem,SizeOf(ElementType));{Вот здесь и возникает ОШИБКА!!!}
dispose(S.Top);
S.Top:=top;
S.Size:=S.Size-Sizeof(ElementType)-SizeOf(pStackElem)*2-SizeOf(Pointer);
end
end;


Автор: Гость 30.11.2006 6:39

дополнение:

pStackElem = ^StackElem;
pElement = ^Element;
StackElem = record
Elem:Pointer;
Next:pStackElem;
end;

Stack = record
Top: pStackElem;
Size: Integer;
end;

Element = record
data:byte;
end;
ElementType = Element;

Автор: ангел 30.11.2006 17:44

Вроде бы все так делаю:
сколько выделил места в памяти под указатель - столько и освобождаю:

...
GetMem(P^.Elem,SizeOf(ElementType));
...


...
FreeMem(S.Top^.Elem,SizeOf(ElementType));
...



Автор: lapp 30.11.2006 18:56

Ты в операторе Move используешь указатель вместо самой величины. Этим самым ты портишь пойнтер.

procedure Push(E:Element;var S:Stack);
var
P:pStackElem;
begin
P:=new(pStackElem);
GetMem(P^.Elem,SizeOf(Element));
Move(E,P^.Elem^,SizeOf(Element)); {было Move(E,P^.Elem,SizeOf(ElementType));}
P^.Next:=S.Top;
S.Top:=P;
S.Size:=S.Size+Sizeof(Element)+SizeOf(pStackElem)*2+SizeOf(Pointer);
end;

procedure Pop(S:Stack;var E:Element);
var
top:pStackElem;
begin
if S.Top<>nil then begin
Move(S.Top^.Elem^,E,SizeOf(Element)); {было Move(S.Top^.Elem,E,SizeOf(Element));}
top:=S.Top^.Next;
FreeMem(S.Top^.Elem,SizeOf(Element));{Вот здесь и возникает ОШИБКА!!!}
dispose(S.Top);
S.Top:=top;
S.Size:=S.Size-Sizeof(Element)-SizeOf(pStackElem)*2-SizeOf(Pointer);
end
end;

Автор: int64 30.11.2006 19:27

Цитата(lapp @ 30.11.2006 14:56) *

Ты в операторе Move используешь указатель вместо самой величины. Этим самым ты портишь пойнтер.

ужас! какая глупая ошибка моя ... wacko.gif невнимательность (((
не таким образом я "разжевал" параметры процедуры Move )))
большое спасибо вам, lapp!

Автор: lapp 30.11.2006 19:40

Цитата(int64 @ 30.11.2006 16:27) *

ужас! какая глупая ошибка моя ... wacko.gif невнимательность (((

smile.gif бывает..
Хочешь совет? Если совсем ничего не получается долгое время, то начинай убирать из программы все "несущественное". Либо на некотором этапе ошибка пропадет (как сейчас), либо ты упростишь себе задачу, освободившись от шелухи.
Успехов!

Автор: volvo 30.11.2006 19:41

А ошибка по-прежнему возникает... smile.gif

Переезжаем в Задачи...

Автор: int64 30.11.2006 19:44

Цитата(volvo @ 30.11.2006 15:41) *

А ошибка по-прежнему возникает... smile.gif

Переезжаем в Задачи...

угу возникает - уже пофиксил wink.gif
а именно это исправил:
Код
procedure Pop(S:Stack;var E:Element);


на

Код
procedure Pop(var S:Stack;var E:Element);


TO lapp: да действительно не впервые.... хотя некоторые участки кода я убирал (комментировал) все равно не решало проблему... Все зависит от того насколько грубо мы ошиблись )

Автор: int64 30.11.2006 19:55

еще один вопрос касаемый реализации стека...
Размер одного элемента стека.
Я таким образом его задал -

Код
sizeOne=Sizeof(Element)+SizeOf(pStackElem)*2+SizeOf(Pointer);


исходя из определенных типов данных
Код
StackElem = record   {Элемент стека}
              Elem:Pointer;       {указатель на данные}
              Next:pStackElem;
              end;
    Stack = record
          Top: pStackElem;
          Size: Integer;
          end;
    Element = record
            .....
            end;


я правильно рассудил?

Автор: Bokul 1.12.2006 9:27

А почему нельзя просто

sizeOne=Sizeof(StackElem)

?

Автор: volvo 1.12.2006 13:09

Цитата
А почему нельзя просто
Потому что это будет "неправильный мед" (С) Винни-Пух... Стек содержит указатель, который в свою очередь содержит адрес выделенной памяти, а насколько я понимаю автора, ему нужен именно размер области памяти, занимаемый самой структурой + той областью, где хранятся данные; то есть, насколько уменьшилось количество доступной памяти в куче при размещении в стеке очередного элемента...

Автор: int64 2.12.2006 5:10

volvo верно рассудил good.gif

но ведь мне не очень то понятно что именно является "размером стека" - не путать с количеством элементов в стеке... Размер которые занимают данные? или размер всего структуры организации стека?
ну я выбрал последнее... правда на самом деле в из кучи при создании очередного элемента (путем new и GetMem) берется больше байтов чем в sizeOne..

Автор: Bokul 2.12.2006 5:15

Цитата
правда на самом деле в из кучи при создании очередного элемента (путем new и GetMem) берется больше байтов чем в sizeOne.

Это ты о чем?

Автор: volvo 2.12.2006 5:36

Цитата
Это ты о чем?
О том, что GetMem/New выделяют память блоками с размером кратным 8... yes2.gif

Автор: Bokul 2.12.2006 5:41

Цитата
правда на самом деле в из кучи при создании очередного элемента (путем new и GetMem) берется больше байтов чем в sizeOne.

Это мы знали. smile.gif
Цитата
берется больше байтов чем в sizeOne..

Ну тогда, если это и имелось ввиду, то правильней будет - больше или ровно...