Когда я должен установить переменную "Nothing" в VB6? - PullRequest
10 голосов
/ 27 августа 2008

В одной из моих форм VB6 я создаю несколько других объектов Form и сохраняю их в переменных-членах.

Private m_frm1 as MyForm
Private m_frm2 as MyForm

// Later...
Set m_frm1 = New MyForm
Set m_frm2 = New MyForm

Я замечаю, что я теряю память всякий раз, когда эта (родительская) форма создается и уничтожается. Обязательно ли мне присваивать эти переменные-члены для Nothing в Form_Unload()?

В общем, когда это требуется?

РЕШЕНО: Эта конкретная утечка памяти была исправлена, когда я делал Unload в соответствующих формах, а не когда я устанавливал форму на Nothing. Мне удалось устранить несколько других утечек памяти, явно установив для некоторых экземпляров модулей классов значение Nothing.

Ответы [ 8 ]

8 голосов
/ 27 августа 2008

@ Мэтт Диллард - Помогло ли это установить утечку памяти?

VB6 не имеет формального сборщика мусора, больше того, что сказал @Konrad Rudolph.

На самом деле вызов unload в ваших формах представляется мне лучшим способом убедиться, что основная форма очищена и каждая подчиненная форма очищает свои действия.

Я проверил это с пустым проектом и двумя пустыми формами.

Private Sub Form_Load()
  Dim frm As Form2
  Set frm = New Form2
  frm.Show
  Set frm = Nothing
End Sub

После запуска обе формы остаются видимыми. установка frm на ничего не удалась ... ничего.

После того, как ничего не задано, единственная ручка, открытая для этой формы, - через ссылку.

Unload Forms(1)

Правильно ли я вижу проблему?

  • Josh
8 голосов
/ 27 августа 2008

На самом деле, VB6 реализует RAII так же, как C ++, что означает, что локально объявленные ссылки автоматически устанавливаются на Nothing в конце блока. Точно так же он должен автоматически сбрасывать переменные класса члена после выполнения Class_Terminate. Тем не менее, было несколько сообщений, что это не сделано надежно. Я не помню ни одного строгого теста, но всегда лучше всего вручную сбрасывать переменные-члены.

4 голосов
/ 29 сентября 2008

Объекты в VB имеют счетчик ссылок. Это означает, что объект ведет подсчет того, сколько других переменных объекта содержат ссылку на него. Когда нет ссылок на объект, объект мусора (в конце концов). Этот процесс является частью спецификации COM.

Обычно, когда локально созданный объект выходит из области видимости (т.е. выходит из подпрограммы), его счетчик ссылок уменьшается на единицу, другими словами, переменная, ссылающаяся на объект, уничтожается. Поэтому в большинстве случаев вам не нужно явно устанавливать объект равным Nothing при выходе из Sub.

Во всех других случаях вы должны явно установить для переменной объекта значение Nothing, чтобы уменьшить ее счетчик ссылок (на единицу). Установка переменной объекта в Nothing, не обязательно уничтожит объект, вы должны установить ВСЕ ссылки на Nothing. Эта проблема может стать особенно острой с рекурсивными структурами данных.

Еще одно замечание - использование ключевого слова New в объявлении переменной объекта. Объект создается только при первом использовании, а не в том месте, где используется ключевое слово New. Использование ключевого слова New в объявлении будет воссоздавать объект при первом использовании каждый раз, когда его счетчик ссылок обнуляется. Так что установка объекта в Nothing может уничтожить его, но объект будет автоматически воссоздан при повторной ссылке. В идеале вы должны объявлять не ключевое слово New, а оператор New, который не имеет такого поведения воскресения.

4 голосов
/ 27 августа 2008

@ Martin

VB6 имел оператор «With / End With», который работал «как» оператор Using () в C # .NET. И, конечно, чем меньше у вас глобальных вещей, тем лучше для вас.

With / End With не работает как оператор Using, он не «Dispose» в конце оператора.

With / End With работает в VB 6 так же, как и в VB.Net, это в основном способ ярлыка вызова свойств / методов объекта. например,

с клиентом .FirstName = "Джон" .LastName = "Смит" Конец с

2 голосов
/ 22 июля 2009

Одним важным моментом, который еще не был упомянут здесь, является то, что установка ссылки на объект на Nothing приведет к запуску деструктора объекта (Class_Terminate, если класс был написан на VB), если нет других ссылок на объект (ссылка количество равно нулю).

В некоторых случаях, особенно при использовании шаблона RAII, код завершения может выполнять код, который может вызвать ошибку. Я полагаю, что это имеет место с некоторыми из классов ADODB. Другим примером является класс, который инкапсулирует файловый ввод-вывод - код в Class_Terminate может попытаться сбросить и закрыть файл, если он все еще открыт, что может вызвать ошибку.

Поэтому важно помнить, что установка ссылки на объект на Nothing может вызвать ошибку и соответственно устранить ее (как именно это будет зависеть от вашего приложения - например, вы можете игнорировать такие ошибки, вставив «On Error Resume Next» перед "Set ... = Nothing").

2 голосов
/ 27 августа 2008

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

Я поднял старый код, и он выглядит примерно так:

Dim y As Long
For y = 0 To Forms.Count -1
    Unload Forms(x)
Next

Может быть безопаснее выгрузить m_frm1. и не просто установить его в ничто.

2 голосов
/ 27 августа 2008

Установка ссылки VB6 на Nothing, уменьшает количество ссылок, которые VB имеет для этого объекта. Если и только если счетчик равен нулю, объект будет уничтожен.

Не думайте, что только из-за того, что вы установили Nothing, он будет "собирать мусор", как в .NET

VB6 использует счетчик ссылок.

Рекомендуется устанавливать экземпляры объектов "Ничего", которые ссылаются на код C / C ++ и тому подобное. Прошло много времени с тех пор, как я коснулся VB6, но я помню, что ничего не настраивал для файлов и ресурсов.

В любом случае это не повредит (если это уже было Ничто), но это не значит, что объект будет уничтожен.

VB6 имел оператор «With / End With», который работал «как» оператор Using () в C # .NET. И, конечно, чем меньше у вас глобальных вещей, тем лучше для вас.

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

2 голосов
/ 27 августа 2008

Строго говоря, никогда, но это дает сборщику мусора сильный намек на уборку.

Как правило: делайте это каждый раз, когда вы закончите с созданным вами объектом .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...