VBScript, кажется, GC'ing объекты из вложенных областей в неправильном порядке - PullRequest
4 голосов
/ 14 сентября 2010

У меня есть следующий код:

function p (str)
    Response.Write VBLF & str
end function

function nop: end function

class Test1
    private sub class_initialize
        p "Test1 Start"
    end sub

    private sub class_terminate
        p "Test1 End"
    end sub
end class

class Test2
    private sub class_initialize
        p "    Test2 Start"
    end sub

    private sub class_terminate
        p "    Test2 End"
    end sub
end class

Когда я бегу:

with new Test1
    with new Test2
    end with
end with

Я ожидаю выхода:

Test1 Start
    Test2 Start
    Test2 End
Test1 End

Но я получаю:

Test1 Start
    Test2 Start
Test1 End
    Test2 End

Однако, я получаю то, что ожидал, если я выполню одно из следующих действий:

with new Test1
    with new Test2
        nop
    end with
end with

with new Test1
    with new Test2
    end with
    nop
end with

Но не следующее:

with new Test1
    nop
    with new Test2
    end with
end with

VBScript имеет довольно сильную гарантию об объектах GC сразу, и я использую (злоупотребляю?) Эту гарантию для различных целей в моих приложениях. Без nop, почему он собирает Test1 и Test2 в «неправильном» порядке?

1 Ответ

10 голосов
/ 17 сентября 2010

Какая захватывающая ошибка.

У меня нет удобной отладочной сборки движка VBScript. (Десятилетний жесткий диск, на котором я его держал, явно испортился через два года с тех пор, как я в последний раз смотрел его.) Однако я легко могу догадаться, что здесь происходит. Я подозреваю, что я не пометил инструкцию, соответствующую «end», как точку, в которой закончился оператор, и сборщик должен работать.

Давайте рассмотрим эту гипотезу.

В вашем первом примере, когда запустится GC? Когда программа заканчивается. В этот момент терминаторы запускаются в том порядке, в котором они были созданы. (Это деталь реализации, на которую не следует полагаться.)

В вашем втором и третьем примере конец вызова nop вызывает GC, и это происходит сразу после окончания с. (Я не совсем уверен, почему во втором примере запускается сборщик мусора, когда объект пригоден для сбора; я не помню точную семантику кода для извлечения ссылки на объект из области видимости блока.)

В вашем четвертом примере GC запускается перед внутренним с и ничего не делает.

Поскольку я написал и логику завершения, и изрядное количество кода обработки «с», я, несомненно, вызвал эту ошибку, поэтому очень много извинений. Поскольку, по-видимому, мы жили с ним без особых проблем в течение последних одиннадцати или двенадцати лет, и поскольку это влияет только на блоки «с», в которых нет содержимого, я не думаю, что это когда-либо будет исправлено.

В любом случае, вы не должны полагаться на приказ о расторжении. Это плохая практика программирования.

Подробнее об увлекательной теме логики завершения VBScript см .:

Каков порядок уничтожения объектов в VBScript?

...