Разбил процедуру на две. В результате - ошибка!

Тема в разделе "Delphi - FAQ", создана пользователем overall, 17 июн 2007.

Статус темы:
Закрыта.
  1. overall

    overall Гость

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

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

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

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

    Код (Text):
    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" (системный модуль).

    Код (Text):
    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 (процедура стандартного менеджера памяти).
    Руками память не выделяю. Только создание и уничтожение объектов, ну и строки (длинные).
    Но если дело с памятью, то почему тогда всё отлично работает, когда процедура не разбита? Не понимаю...

    Подскажите, что-нибудь, пожалуйста!
     
  2. overall

    overall Гость

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

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

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

    Код (Text):
     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, но сделал это неправильно.

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

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

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

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


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

    Barmutik Гость

    Честно говоря я как-то соабо верю что это был действительно баг компилятора Delphi.. мне уже самому много раз так казалось.. но в итоге выяснялось что не прав таки я...

    По Вашему коду сложно что-то сказать.. потому как большая часть кода отсутствует...
     
Загрузка...
Похожие Темы - Разбил процедуру на
  1. sowhat
    Ответов:
    0
    Просмотров:
    647
  2. phantom76
    Ответов:
    10
    Просмотров:
    4.050
Статус темы:
Закрыта.

Поделиться этой страницей