Нужна ли "зачистка мусора" в VBA?

Иван FXS
Дата: 18.11.2006 20:58:01
Если есть коллекция С, в которой находится некоторое количество объектов, которые – ТОЛЬКО В НЕЙ, т.е. все прочие указывавшие на них переменные уже "зачищены" (перестали существовать);
и если я делаю этой коллекции
Set C = Nothing
- то будут ли (автоматически) удалены из памяти все эти объекты?
Latuk
Дата: 18.11.2006 23:16:05
да
Старый ворчун
Дата: 19.11.2006 00:38:32
Надо рассматривать конкретную ситуацию. Если объект коллекции - класс и имеются перекрестные ссылки, то хотя после Set C = Nothing коллекция С будет Nothing, но объекты-классы, будут существовать, это можно проверит по выполнению (или невыполнению) события Terminate.
бабай
Дата: 19.11.2006 02:12:40
Старый ворчун
... Если объект коллекции - класс и имеются перекрестные ссылки, то хотя после Set C = Nothing коллекция С будет Nothing но объекты-классы, будут существовать ...


возможно следует уточнить для автора вопроса, что в таком случае не только классы, составляющие коллекцию не будут разрушены, но и сама коллекция тоже останется в памяти.
Разрушать ее придется с использованием явного цикла Remove

(извините за уточнение. считаю, что это не обязательно очевидно из предыдущего ответа)
Иван FXS
Дата: 19.11.2006 11:22:17
Старый ворчун
"перекрестные ссылки" – очевидно, имеются в виду ссылки, указывающие НА объекты этой коллекции, однако не понятно мне – указывающие ОТКУДА? У ссылки ведь две стороны, правда?

All
Мы ведь различаем – в контексте вопроса – уничтожение СОДЕРЖАНИЯ (объектной) ПЕРЕМЕННОЙ и зачистку ПАМЯТИ! В теме про "мусор" речь идет, конечно, про второе.

(Уничтожение содержания (объектной) переменной: этим я называю ситуацию, когда - вернувшись в контекст, где эта переменная существует - мы обнаруживаем, что он Is Nothing.)

Мусор – это когда память, выделенная программе не уменьшилась при уничтожении (содержания) переменной.

Бабай
"не только классы ... не будут разрушены"
- классы? Или объекты – экземпляры классов??
Если экземпляры, то – дополнительный вопрос на понимание: "не будут разрушены" – в смысле "останутся в памяти" (в виде мусора)? Нет ведь больше никаких ни переменных, ни конструкций, посредством которых можно было бы обратиться к ЭТИМ экземплярам, и ИМЕВШИМСЯ значениям их атрибутов, например!

"сама коллекция тоже останется в памяти" – в виде мусора? Как можно в этом убедиться? Наблюдая за выделенной программе памятью? Но не понятно, как различить память выделенную под "саму коллекцию" от памяти, выделенной под "ее" объекты?
Иван FXS
Дата: 19.11.2006 11:46:20
Добавлю: убедиться, что объект не подвергся уничтожению, по тому, что не наблюдалось выполнение его метода Terminate, - это эврика, спасибо, Старый ворчун!

Но у коллекции-то нет метода Terminate ...
Старый ворчун
Дата: 19.11.2006 11:50:07
Правильнее сказать "циклические ссылки": в X есть переменная, ссылающаяся на Y, в Y есть переменная, сссылающаяся на X.
автор
(Уничтожение содержания (объектной) переменной: этим я называю ситуацию, когда - вернувшись в контекст, где эта переменная существует - мы обнаруживаем, что он Is Nothing.)

Мусор – это когда память, выделенная программе не уменьшилась при уничтожении (содержания) переменной.

Объектная переменная может быть уничтожена, а сам объект - нет, хотя переменных ссылающихся на него нет. И я не уверен, что это следует называть "мусором". Свой код такой объект тоже будет выполнять.
Старый ворчун
Дата: 19.11.2006 12:01:20
Иван FXS
Добавлю: убедиться, что объект не подвергся уничтожению, по тому, что не наблюдалось выполнение его метода Terminate, - это эврика, спасибо, Старый ворчун!

Но у коллекции-то нет метода Terminate ...

Для коллекции можно использовать специальный класс. У Гетца, где-то есть описание.
В процедуре Dispose этого класса-коллекции вызываете последовательно процедуру Dispose объектов коллекции, в которой уничтожаются все ссылки на другие объекты.
После этого уничтожаете коллекцию.

Есть и другие меьоды борьбы с циклическими ссылками, основанные на прямых манипуляциях с памятью.
Иван FXS
Дата: 19.11.2006 14:46:20
Старый ворчун
Должна быть какая-то Shell (или ядро), в которой этот объект "зарегистрирован" – в виде какой-то переменной и какого-то атрибута (какого-то другого объекта) ... иначе я не понимаю, на каком основании этот объект (нигде не "прописанный") будет функционтровать? На каком основании "управление" будет передаваться "своему коду такого объекта"?

Старый ворчун: "Для коллекции можно использовать специальный класс"

- нет, я говорил про "базовые" коллекции языка (VB), а не про "самопальные"!
бабай
Дата: 19.11.2006 16:27:19
Иван FXS

Бабай
"не только классы ... не будут разрушены"
- классы? Или объекты – экземпляры классов??

объекты – экземпляры классов


Иван FXS

Если экземпляры, то – дополнительный вопрос на понимание: "не будут разрушены" – в смысле "останутся в памяти" (в виде мусора)?

"не будут разрушены" – в смысле "останутся в памяти"


на остальное отвечу так:

пусть у вас есть тестовый класс Class1

Option Compare Database
Option Explicit

Private parentObj   As Object

Private Sub Class_Initialize()
  Debug.Print "Initialize:" & ObjPtr(Me)
End Sub

Private Sub Class_Terminate()
   Debug.Print "Terminate:" & ObjPtr(Me)
End Sub

Property Set setParent(ByVal pObj As Object)
    Set parentObj = pObj
End Property

Property Get getParent() As Object
    Set getParent = parentObj
End Property

поэкспериментируйте с ним.
например так (стандартный модуль):

Dim pC As Class1

Sub simpleTEst()
  Dim obj1 As Class1
  Dim obj2 As Class1
  
  Set obj1 = New Class1
  Set obj2 = New Class1
  
  Set obj2.setParent = obj1 ' объект2 ссылается на объект 1. В этой точке циклической ссылки еще нет.
  Set obj1.setParent = obj2 ' завершение циклической ссылки - теберь эта пара будет вечной
  
End Sub

Sub Test()
    Dim pObj As Class1
    Dim tC As Collection
    
    Set pObj = New Class1
    'следующая строка нужна для того, чтобы зацепиться за коллекцию впоследствии.
    'если ее выключить из исполнения - окончательно потеряются следы объектов
    'но сами объекты останутся в памяти
    Set pC = pObj
    
    Set tC = New Collection
    tC.Add pObj, "K1"
    Set pObj.setParent = tC 'это организация циклической ссылки.
                            ' TC содержит ссылку на pObj, а pObj ссылку на TC
    
    Set pObj = New Class1
    tC.Add pObj, "K2"
    Set pObj.setParent = tC
    
    Set tC = Nothing
    'если PC сформирован, то
    'добраться до коллекции впоследствии можно
    'запустите Sub2
End Sub

Sub sub2()
    Dim mC As Collection
  If Not pC Is Nothing Then
    Set mC = pC.getParent
    If Not mC Is Nothing Then
    Debug.Print mC.Count
    End If
  End If
End Sub