Помощь - Поиск - Пользователи - Календарь
Полная версия: Работа с динамикой
Форум «Всё о Паскале» > Pascal, Object Pascal > Задачи
Relrin
Делаю задачу по следующему условию:
Изображение

С того момента, как написал процедуру, которая складывает элементы очередей(например, 1 в первой ячейки очереди А, во второй Б соответственно 2, например. Я их складываю, и значения первой ячейки А, перезаписываю на результат сумму, при этом элемент Б, который использовался, освобождаю с помощью FreeMem.), FreePascal начал выдавать ошибку на указателе (знаке ^) с текстом "Internal Error 200507031", хотя вроде бы как все правильно... Может быть кто-нибудь сталкивался с такой ошибкой, и знает ее решение?

Исходный код программы приведен в аттаче.
volvo
Версия FPC? Настройки компилятора изменял? 2.4.2 откомпилировал и даже не поперхнулся...
Relrin
Версия 2.4.0
volvo
Обновляй.

К тому же, есть еще одно место, которое выглядит не очень хорошо (по крайней мере, у меня при запуске начались с ним проблемы). Не используй GetMem/FreeMem, работай с New/Dispose. Вот тут (процедура DivisionDeck):
    {перенос части в очередь а}
if i<=5 then
begin
{переносим в ячейку число (очередь а) из дека}
a.next1^.elem:=c.front^.elem;
{запоминаем ссылку дека}
adr:=c.front^.next;
{переходим к следующей ссылке дека}
c.front^.next:=c.front^.next^.next;
{освобождаем память предыдущей ячейки, т.к. использовалии ее}
{и она нам больше не потребуется в дальнейшем}
{*} FreeMem(adr,SizeOf(adr));
{выделяем память для нового элемента очереди а}
GetMem(a.next1^.next,sizeof(a.next1^.next));
{заносим в нее ссылку}
a.next1^.next:=a.next1^.next^.next;
end

программа падает. Если заменить во всей программе GetMem(X, Size) на New(X), а FreeMem(X, Size) на Dispose(X), то вылета уже не происходит...
Relrin
Вылеты программы у меня наблюдается, правда она где-то зарыта в области процедуры PlusQueue
volvo
Так. Стоп...

Ты заполнил Дек, так? Проверял, правильно ли он заполнился (т.е., правильно ли установлены указатели)? Процедура PrintDeck у тебя присутствует? Нет. Проверяй...

Дальше: разбил дек на 2 очереди. Ты проверил, правильно ли разбил? Процедура PrintQueue есть? Нет. Проверяй...

Не надо искать ошибки в последующих действиях, пока не убедился, что все предыдущие выполнены правильно. У тебя такой уверенности нет.

Потом. Вот такие конструкции a.next1^.next:=a.next1^.next^.next; с легкостью приводят к вылету программы. Если где-то будет nil или невалидный указатель. Ты опять же этого не поверяешь. Зачем тебе вообще такие многоэтажные конструкции? Что, нельзя сделать сумму очередей, не прибегая к "одноэтажной" адресации? Вот так, в смысле:
while q1 <> nil do
begin
AddToQueue (q_result, q1^.elem + q2^.elem);
q1 := q1^.next; q2 := q2^.next;
end;
? Если ты корректно разбил исходную очередь на две одинаковых по длине (зачем был приплетен Дек я тоже не понимаю, в задаче о нем нет ни слова) - то это будет прекрасно работать... Кстати, для того, чтоб разбить длинную очередь на 2 коротких, совсем не обязательно удалять значения из одной очереди и записывать их в другую. Все, что для этого нужно - это переприсвоить 4 указателя. Прописью: четыре!!! И потом можно просто работать с теми же данными, но уже не в виде очереди длиной 2*n, а в виде двух очередей длиной n каждая.

Почему работаешь через глобальные переменные - тоже не совсем понятно. Хочется глюки поотлавливать? Вот ты и занимаешься этим. Тебе удалось...
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.