Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 17.06.2007, 06:33   #1
overall
Новичок
Джуниор
 
Регистрация: 17.06.2007
Сообщений: 2
По умолчанию Разбил процедуру на две. В результате - ошибка!

Здравствуйте. Вот такая вот фигня у меня. Уже третий день сижу мучаюсь не могу понять, где что не так.

Была процедура следующего вида:

Весь код не привожу, больно большой.

Код:
procedure ReadItemsTo(...);
var
  I: Integer;
begin
  for I := 0 to ... do
  begin
    //Кусок кода #1
  end;
end;
Разбил её на две, путем выноса из под цикла:

Код:

function ReadItem(...): ...;
begin
  //Кусок кода #1
end;

procedure ReadItemsTo(...);
var
  I: Integer;
begin
  for I := 0 to ... do
  begin
    ... := ReadItem(...);
  end;
end;
Вынес правильно.

В старой версии процедура рекурсивно вызывала саму себя.
После разбивки соответственно рекурсия сохранилась, но опосредованно (ReadItemsTo -> ReadItem -> ReadItemsTo -> ReadItem -> ...).

Компилится и работает, но в некоторых случаях
возникает AV (Access Violation) в процедуре "DeleteFree()" в "getmem.inc" (системный модуль).

Код:
procedure DeleteFree(f: PFree);
var
  n, p: PFree;
  size: Integer;
begin
  if rover = f then
    rover := f.next;
  n := f.next;
  size := f.size;
  if size <= cSmallSize then begin
    if n = f then
      smallTab[size div cAlign] := nil
    else begin
      smallTab[size div cAlign] := n;
      p := f.prev;
      n.prev := p;
      p.next := n;
    end;
  end else begin
    p := f.prev;
    n.prev := p; // Здесь!!!
    p.next := n;
  end;
end;

Всё это определенно очень странно.
До разбития процедуры всё работало отлично без таких вот выкрутасов.
Может это баг компилятора? (Пробовал и на Delphi 5 и на Delphi 6 - и там и там таже самая ошибка)

Думаю, может что-то не так с выделением памяти, раз ошибка в DeleteFree (процедура стандартного менеджера памяти).
Руками память не выделяю. Только создание и уничтожение объектов, ну и строки (длинные).
Но если дело с памятью, то почему тогда всё отлично работает, когда процедура не разбита? Не понимаю...

Подскажите, что-нибудь, пожалуйста!
overall вне форума Ответить с цитированием
Старый 18.06.2007, 05:18   #2
overall
Новичок
Джуниор
 
Регистрация: 17.06.2007
Сообщений: 2
По умолчанию

Разобрался сам.

Это был баг компилятора Delphi.

Смотреть ассемблерный код не стал, разбираться что да почему.

Код:
  procedure ReadItemsTo(ARuleItemList: TRuleItemList; const APrefix: string);
  var
    ItemCount: Integer;
    I: Integer;
    ItemPrefix: string;

    RuleItem: TRuleItem;
  begin
    ItemCount := ...;

    for I := 0 to ItemCount - 1 do
    begin
      ItemPrefix := APrefix + ...;

      RuleItem := ReadItem(ItemPrefix);

      ARuleItemList.Add(RuleItem);
    end;
  end;

  function ReadItem(const APrefix: string): TRuleItem;
  var
    ItemPrefix: string;
    RuleItem: TRuleItem;
    ...
  begin
    RuleItem := nil;

    ItemPrefix := APrefix;

    // А здесь интенсивно ипользуется ItemPrefix
    ...

    Result := RuleItem;
  end;
Так вот из-за присвоения:

ItemPrefix := APrefix;

вся фигня и была.

Дело в том, что параметр APrefix больше нигде не используется в этой процедуре.
И видимо компилятор не производил никакого присваивания, а как-то
с оптимизировал код, что просто APrefix "стал" ItemPrefix, но сделал это неправильно.

После того, как переписал процедуру вот так:

Код:
  function ReadItem(const APrefix: string): TRuleItem;
  var
    RuleItem: TRuleItem;
    ...
  begin
    RuleItem := nil;

    // А здесь интенсивно ипользуется APrefix
    ...

    Result := RuleItem;
  end;
никаких багов нет и GetHeapStatus не возвращает ошибки.


В компиляторе Delphi 6 есть так же баг с переполнением стека FPU, размер которого 8 элементов.
И при вычислении БОЛЬШОГО выражения с вещественными числами (на практике такие выражения встречаются наверное почти никогда),
приводит к исключению, а именно к переполнению стека FPU. Они уж хотя бы проверку в компилятор добавили бы,
что мол выражение слишком большое - переформулируйте.
overall вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Переделать процедуру AidarBik Общие вопросы Delphi 12 22.05.2008 14:59
подскажите процедуру Nova БД в Delphi 5 15.05.2008 16:43
присвоить переменной целого типа значение поля key полученное в результате выполнения SQL запроса Worms БД в Delphi 5 10.01.2008 21:07
Как вызвать процедуру ??? Marat Помощь студентам 8 02.03.2007 15:11