Чистота программного кода: уничтожение объектов

Программирование на Visual Basic, главный форум. Обсуждение тем программирования на VB 1—6.
Даже если вы плохо разбираетесь в VB и программировании вообще — тут вам помогут. В разумных пределах, конечно.
Правила форума
Темы, в которых будет сначала написано «что нужно сделать», а затем просьба «помогите», будут закрыты.
Читайте требования к создаваемым темам.
PSV
Продвинутый пользователь
Продвинутый пользователь
 
Сообщения: 154
Зарегистрирован: 29.01.2002 (Вт) 12:30
Откуда: Россия

Чистота программного кода: уничтожение объектов

Сообщение PSV » 30.05.2003 (Пт) 7:32

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

Например, вызываем процедуру, в которой

Dim rs As new ADODB.recordset

или даже

Dim rs As ADODB.recordset

Set rs = new ADODB.recordset

Если я не возвращаю ссылок на этот рекордсет (ну или др. объект), и не делаю на него ссылок из глобальных переменных, то, насколько я понимаю, он АВТОМАТИЧЕСКИ уничтожается при завершении процедуры. Даже если произошла ошибка, а обработчик в процедуре, которая вызывала эту. Т.е. не нужно так уж обязательно лепить

Set rs = Nothing

в конце этой процедуры.

По крайней мере, смотря на примеры из MSDN можно понять так.

То же, видимо, действует в случае, если объявить глобальную переменную в каком-нить модуле:

Public rs As new ADODB.recordset

Данный объект, получается, должен удаляться АВТОМАТИЧЕСКИ при завершении программы.

Ну и последний пример.

Вызывающая процедура имеет:

Dim rs As ADODB.recordset

Вызываем процедуру:

Public Sub SP(..., rs AS ADODB.recordset)

В ней создается объект:

Set rs = cmd.Execute

А вот в этом случае, при завершении родительской процедуры rs тоже будет уничтожен АВТОМАТИЧЕСКИ ... или я не прав?

А, забыл, есть еще часто встречающийся случай - объявляем несколько объектов в классе. Я предпочитаю в деструкторе (Terminate) делать им всем Set ... = Nothing - моэ и это лишнее?

PSV
Продвинутый пользователь
Продвинутый пользователь
 
Сообщения: 154
Зарегистрирован: 29.01.2002 (Вт) 12:30
Откуда: Россия

Сообщение PSV » 30.05.2003 (Пт) 7:56

А, да, еще с закрытием ADO-ых рекордсетов.

Хранимые процедуры возвращают черзе объект Command статические рекордсеты, если они удаляются автоматически, мож их и закрывать тоже не нужно? Замечу что рекордсеты статические и используются только для чтения информации.

skiperski
Идеолог
Идеолог
Аватара пользователя
 
Сообщения: 1386
Зарегистрирован: 25.06.2002 (Вт) 15:52

Сообщение skiperski » 30.05.2003 (Пт) 13:19

А в чём проблема-то? Лень набивать код удаления объектов? Автоматом-то они удаляться должны, но это в VB происходит как получится, а не как задумано. Удаляй всё руками и не думай о том что там должно происходить по-умолчанию.

PSV
Продвинутый пользователь
Продвинутый пользователь
 
Сообщения: 154
Зарегистрирован: 29.01.2002 (Вт) 12:30
Откуда: Россия

Сообщение PSV » 30.05.2003 (Пт) 16:49

skiperski писал(а):А в чём проблема-то? Лень набивать код удаления объектов? Автоматом-то они удаляться должны, но это в VB происходит как получится, а не как задумано. Удаляй всё руками и не думай о том что там должно происходить по-умолчанию.


Ну не то чтобы лень, просто если это лишний код - ну его нафиг, да и мешает иногда при обработке исключительных ситуаций.

А "это в VB происходит как получится" я так понимаю из личного опыта и были преценденты что автомат не срабатывал?

skiperski
Идеолог
Идеолог
Аватара пользователя
 
Сообщения: 1386
Зарегистрирован: 25.06.2002 (Вт) 15:52

Сообщение skiperski » 30.05.2003 (Пт) 17:12

Лучше перебдеть, чем не добдеть!

Проще убить переменные руками ("Я тебя породил, я тебя и убъю!" Тарас Бульба), чем надеяться на компилятор. Может в обычных EXE-шках умолчания прокатят, но при работе под IIS уже - нет. Причём там перед убийством надо проверять на Nothing. И только если обект не Nothing тогда убивать его.

О, замечательный пример для простых EXE-шек: кривая выгрузка форм. Программа завершена, а формы болтаются в памяти. Вот такая вот автоматизация.

Sebas
Неуловимый Джо
Неуловимый Джо
Аватара пользователя
 
Сообщения: 3626
Зарегистрирован: 12.02.2002 (Вт) 17:25
Откуда: столько наглости такие вопросы задавать

Сообщение Sebas » 31.05.2003 (Сб) 9:54

У тебя набор передаётся по ссылке.....)))))
- Я никогда не понимал, почему они приходят ко мне чтобы умирать?

sebas<-@->mail.ru

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 31.05.2003 (Сб) 13:08

skiperski, есть мнение, что Тарас Бульба говорил "чем я тебя породил, тем я тебя и убью" ;)

To subj:
Т.е. если создал через Set, то и убиваешь через Set, если создал автоматом, то убиваешь сначала "сынка", а затем "папу" :)
Lasciate ogni speranza, voi ch'entrate.

PSV
Продвинутый пользователь
Продвинутый пользователь
 
Сообщения: 154
Зарегистрирован: 29.01.2002 (Вт) 12:30
Откуда: Россия

Сообщение PSV » 02.06.2003 (Пн) 8:29

Sebas писал(а):У тебя набор передаётся по ссылке.....)))))


Ну и что - я так понимаю что в "нормальных" условиях возвращенный по ссылке набор затем автоматом грохается при завершении процедуры в которой он объявлен (т.е. куда он был возвращен при помощи ссылки).

По крайней мере я сделал цикл на запуск этих процедур ну очень _большое_ количество раз при условиях что я не закрываю рекордсеты и не делаю Set ... = Nothing - и, судя по расходу памяти прогой в Task Manager, все Ок.

alibek писал(а):skiperski, есть мнение, что Тарас Бульба говорил "чем я тебя породил, тем я тебя и убью" ;)

To subj:
Т.е. если создал через Set, то и убиваешь через Set, если создал автоматом, то убиваешь сначала "сынка", а затем "папу" :)


Не совсем понял кого ты подразумеваешь под "папой" и кого под "сынком".

Тем не менее - лана, _перестраховался_, вернул Set ... = Nothing и закрытие рекордсетов, но код от этого читается хуже и ваще - лишние операции (возможно) - лишний расход CPU.

ASD
Модератор
Модератор
Аватара пользователя
 
Сообщения: 1758
Зарегистрирован: 07.12.2001 (Пт) 21:08
Откуда: Russia

Сообщение ASD » 02.06.2003 (Пн) 11:05

А ты понаблюдай за расходом памяти при явном уничтожении обьекта и при автоматической. И сделай вывод что тебе лучше.

Кстате на счет процессора не беспокойся. Слишком мелкая операция.
Тут тока память играет роль.
Moderator VBStreets
---------------------------

skiperski
Идеолог
Идеолог
Аватара пользователя
 
Сообщения: 1386
Зарегистрирован: 25.06.2002 (Вт) 15:52

Сообщение skiperski » 02.06.2003 (Пн) 11:23

PSV писал(а):но код от этого читается хуже

Могу предложить свой стиль оформления исключительных ситуаций и уничтожения объектов

Есть такой звэр CodeSMART называется. Тама мона прописать всякие полезности. Вот такая вот полезность вставляется в начало каждой процедуры/функции
Код: Выделить всё
    On Error GoTo hErr
    ErrMsg = vbNullString

А вот такая в конец
Код: Выделить всё
    '------- close all and exit (begin)
ExitRoutine:
    On Error Resume Next
    '------- close all and exit (break)
    '------- close all and exit (continue)
    Err.Clear
    Exit {MemberType}
    '------- close all and exit (end)
    '------- error handler (begin)
hErr:
    ErrMsg = DbgWriteToLogErr(Err, "{ProjectName}.{ComponentName}.{MemberName}", Erl)
    Resume ExitRoutine: GoTo ExitRoutine
    '------- error handler (end)

Между строками
Код: Выделить всё
    '------- close all and exit (break)
    '------- close all and exit (continue)

пишем код уничтожения объектов. Одна из часто используемых полезностей
Код: Выделить всё
    If (Not rs Is Nothing) Then
        If (rs.State) Then rs.Close
        Set rs = Nothing
    End If
    If (Not cn Is Nothing) Then
        If (cn.State) Then cn.Close
        Set cn = Nothing
    End If

Т.о. всё скомпановано и всегда на одних и тех же местах. При чтении кода, зная его структуру, перестаёшь обращать внимание на эти вставки и они совсем не мешают.

Разумеется, переменная ErrMsg и функция DbgWriteToLogErr() должны быть определены.

Morfius
Новичок
Новичок
 
Сообщения: 46
Зарегистрирован: 25.03.2003 (Вт) 14:27
Откуда: КМВ

Сообщение Morfius » 02.06.2003 (Пн) 12:44

А CodeSMART ты где взял??? может линк кинишь, где взял???
Жизнь похожа на сказку, - Чем дальше, тем страшнее

skiperski
Идеолог
Идеолог
Аватара пользователя
 
Сообщения: 1386
Зарегистрирован: 25.06.2002 (Вт) 15:52

Сообщение skiperski » 02.06.2003 (Пн) 12:57

Morfius писал(а):А CodeSMART ты где взял??? может линк кинишь, где взял???

В своей конторе. Поиск должен найти, но он денех стоит.

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 02.06.2003 (Пн) 15:40

Когда-то давно читал я мануал... Давно, поэтому могу переврать... В том мануале было сказано, что COM так устроен, что автоматически херит объект, на который не существует ни одной объектной ссылки. Соответственно, если прога закрылась, то исчезли её переменные, и значит COM должен сам похерить все объекты, а не доверять COM, думаю, нет причин...
Или я неправ? :shock:
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

ASD
Модератор
Модератор
Аватара пользователя
 
Сообщения: 1758
Зарегистрирован: 07.12.2001 (Пт) 21:08
Откуда: Russia

Сообщение ASD » 02.06.2003 (Пн) 15:55

Прав то прав. Да бывает не херит сволочь.
Причем я сталкивался с такими фишками.
Типа компонент аля бегущая строка, запускаю проект, все зашибись,
бежит. Останавливаю а у меня в Design Mode этот компонент все бежит!
В Net это решено. Там более продвинутый сборщик мусора.
Moderator VBStreets
---------------------------

gaidar
System Debugger
System Debugger
 
Сообщения: 3152
Зарегистрирован: 23.12.2001 (Вс) 13:22

Сообщение gaidar » 02.06.2003 (Пн) 18:12

Продвинутый? хе-хе. Знаем мы его.
Если объект не используется явно, т.е. ссылок на него нет, то он его сносит, а если болтается ссылка порожденная уже убитым объектом, то нет. В VB6 сносилась за милую душу :)
The difficult I’ll do right now. The impossible will take a little while. (c) US engineers in WWII
I don't always know what I'm talking about, but I know I'm right. (c) Muhammad Ali

ASD
Модератор
Модератор
Аватара пользователя
 
Сообщения: 1758
Зарегистрирован: 07.12.2001 (Пт) 21:08
Откуда: Russia

Сообщение ASD » 03.06.2003 (Вт) 11:04

Мда... фигня полная.

Но думаю правильно будет всеже прибивать явно.
Moderator VBStreets
---------------------------

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 05.06.2003 (Чт) 8:44

Долго думал над всем этим. Пришло такое мне в голову.
Мы когда пишем Set var = Nothing, мы же объект не херим. Это ж не функция какая-нибудь типа DestroyMenu. Мы херим наш pointer, это var который. Причём если пойнтеров на один объект несколько, то ведь прибивание одного из них никогда не приводит к прибиванию объекта (только что проверил). А объект уничтожается только по факту того, что на него больше нет валидных пойнтеров, то есть всё-таки COM его прибивает по своему этому внутреннему правилу.
Тогда вообще непонятно, почему объекты иногда остаются в памяти. А "явное прибивание" теряет смысл, потому что оно, как оказывается, неявное.

Вывод? Что писать Set = Nothing, что не писать, разницы нет :shock:
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 05.06.2003 (Чт) 9:14

Объект ты закрываешь методами самого объекта, например objExcel.Quit или db.Close, в крайнем случае Unload object. А потом прибиваешь указатель на не существующий объект.
Lasciate ogni speranza, voi ch'entrate.

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 05.06.2003 (Чт) 9:34

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


Закон Мэрфи, один из...


Если прибить объект методом самого объекта, то указатель на него автоматически станет Nothing! Проверено!
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

Rainbow
Человек-радуга
Человек-радуга
 
Сообщения: 543
Зарегистрирован: 13.05.2003 (Вт) 14:16

Сообщение Rainbow » 05.06.2003 (Чт) 10:24

Что писать Set = Nothing, что не писать, разницы нет


Ну, думаю, если все-таки уничтожать самостоятельно созданные ссылки на объекты, то все же объекты в большинстве :roll: случаев будут выгружаться.

Был у меня пример из жизни, когда выгружалась форма, а Terminate от юзерских контролов не приходил (соотвественно объекты оставались в памяти). Причиной этому было то, что остались мои собственные ссылки в форме на эти контролы...

skiperski
Идеолог
Идеолог
Аватара пользователя
 
Сообщения: 1386
Зарегистрирован: 25.06.2002 (Вт) 15:52

Сообщение skiperski » 05.06.2003 (Чт) 13:43

GSerg писал(а):Причём если пойнтеров на один объект несколько, то ведь прибивание одного из них никогда не приводит к прибиванию объекта (только что проверил). А объект уничтожается только по факту того, что на него больше нет валидных пойнтеров

Вот тут собака и порылась! Например, имеем класс с древовидной организацией, типа TreeView, т.е. ссылки на родительские эл-ты, на пред. и след. эл-ты и т.д. Теперь отдаём работу по уничтожению объекта VB. И что получаем? При попытке выгрузить родительский объект VB находит ссылку на на него (во всех подчинённых объектах) и оставляет его жить. При этом ссылку на этот объект мы уже потеряли. Затем уничтожаются все ссылки на подчинённые объекты, а сами объекты остаются в памяти, т.к. на них существует ссылка из (ещё не забыли?) не убитого родительского объекта, который уже намертво болтается в памяти. Таким образом мы уничтожаем все сылки на объекты, а сами объекты остаются живы-живёхоньки, но уже без надежды до них достучаться. Хорошо разветвлённый объект при интенсивном использовании сжирает всю оперативку часа за 4-5. Проверено на практике.

Rainbow
Человек-радуга
Человек-радуга
 
Сообщения: 543
Зарегистрирован: 13.05.2003 (Вт) 14:16

Сообщение Rainbow » 05.06.2003 (Чт) 14:29

skiperski писал(а):Таким образом мы уничтожаем все сылки на объекты, а сами объекты остаются живы-живёхоньки, но уже без надежды до них достучаться.


Но это же наша была структура! Деревянная она там или список какой (как было в моем случае) с кучей ссылок элементов друг на друга... Зачем отдавать уничтожение VB? Понятно, он будет пытаться это делать, как умеет. Если мы сами создали такую структуру - надо позаботиться о ее правильном уничтожении. Разве не логично?

skiperski
Идеолог
Идеолог
Аватара пользователя
 
Сообщения: 1386
Зарегистрирован: 25.06.2002 (Вт) 15:52

Сообщение skiperski » 05.06.2003 (Чт) 14:43

Ну, дык, а кто спорит? Я и говорю, что прибивать надо! А чтобы не заморачиваться кто свой, а кто чужой (в смысле удаляется автоматом) бей всех, там наверху потом рассортируют.


Вернуться в Visual Basic 1–6

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 29

    TopList  
cron