Когда мне нужно установить для переменной значение «Ничего» в VB6?

StackOverflow https://stackoverflow.com/questions/30354

  •  09-06-2019
  •  | 
  •  

Вопрос

В одной из моих форм 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, также.

Это было полезно?

Решение

@Matt Dillard - Установка этих значений на ничего не устранила утечку памяти?

В 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)

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

  • Джош

Другие советы

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

@Мартин

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

With/End With не работает так же, как оператор using, он не «удаляет» в конце оператора.

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

С acustomer .firstname = "John" .lastname = "Smith" заканчивается с

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

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

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

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

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

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

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

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

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

Вам рекомендуется установить экземпляры объектов «Ничего», которые ссылаются на код C/C++ и тому подобное.Давно я не прикасался к VB6, но помню, что файлы и ресурсы обнулялись.

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

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

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

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

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

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

Возможно, безопаснее выгрузить файл m_frm1.а не просто установить его на нет.

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top