2008-11-05 1 views
2

Есть ли такая вещь?Динамическое распределение памяти в VB6

Я говорю о чем-то вроде команды C++ new, т.е. о распределении памяти, что требует явного освобождения памяти (или утечек памяти риска).

Я спрашиваю, потому что я помню, чтобы решить некоторые проблемы утечки GDI ранее установкой формы/управления/другие объекты Nothing, но не могу вспомнить, что и почему сейчас ...

ли мы когда-нибудь придется беспокоиться о управление памятью при разработке в VB6?

ответ

7

Существует несколько проблем, связанных с управлением памятью в VB6.

Первыми являются круговые ссылки, где дочерний класс указывает на родителя и наоборот. Без явной установки ссылки на Nothing, это иногда относится к формам, а особенно к диалогу, который является редактором для объекта Target. Снова убедившись, что все, что ни к чему, решит проблему.

Основополагающими принципами являются: 1) Если что-либо, на которое указывает объект, является «живым», то это не будет собирать мусор. Поэтому, когда вы устанавливаете ссылку на родительский объект круглой ссылки, ребенок жив, поэтому родитель не получает сбор мусора, так как родитель все еще жив, ребенок не получает собранный мусор.

То же самое с формами. Если вы не установили свойство Target в диалоговом окне, которое ничего не редактирует, он не будет запускать финальную серию событий до тех пор, пока объект цели жив.

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

Что касается утечек GDI, в любое время вы используете внешнюю DLL, которая использует ручки, указатели. Вы ставите себя в ту же область, что и C++ для этих функций. Таким образом, вы должны следить за тем, чтобы вы соблюдали все правила конкретного API или DLL, которые вы используете, что часто подразумевает явное уничтожение того, что вы создали после того, как вы сделали с ним.

Существует элегантное решение для круглого задания. Вместо того, чтобы ребенок ссылался на родителя напрямую, вы используете прокси.

Сначала создайте класс прокси для родительского объекта.

Option Explicit Public Event GetRef(ByRef RHS As MyObject) 

Public Function GetMyObject() As MyObject 
    Dim Ref As MyObject 
    RaiseEvent GetRef(Ref) 
    Set GetMyObject = Ref 
End Function 

Затем определяют приватную переменную в Родитель

Private WithEvents MyProxy As MyObjectProxy 

Private Sub Class_Initialize() 
    Set MyProxy = New MyObjectProxy 
End Sub 

Тогда настройки только для чтения свойство называется Proxy и реализовать событие GetRef.

Public Property Get Proxy() As MyObjectProxy 
    Set Proxy = MyProxy 
End Property 

Private Sub MyProxy_GetRef(RHS As MyObject) 
    Set RHS = Me 
End Sub 

Для ребенка или чего-либо еще, для которого требуется ссылка, код выглядит следующим образом.

Private ParentProxy As MyObjectProxy 

Public Property Get Parent() As MyObject 
    If ParentProxy Is Nothing Then 
     Set Parent = Nothing 
    Else 
     Set Parent = ParentProxy.GetRef 
    End If 
End Property 

Public Property Set Parent(RHS As MyObject) 
    If RHS Is Me Then 
     Set MyObjectProxy = Nothing 
    ElseIf Target Is Nothing Then 
     Set MyObjectProxy = Nothing 
    Else 
     Set MyObjectProxy = RHS.Proxy 
    End If 
End Property 

Поскольку механизм событий не устанавливает ссылку или увеличивает COM счетчика ссылок на объект либо он избегает всего проблемы циклических ссылок, которая является бичом многих VB6 программистов.

Примечание. Источник, из которого я получил его, назвал его прокси, но, благодаря комментарию Энтони, я считаю, что он также подходит для определения шаблона посредника. Он использует определенную функцию VB6 Centric; API событий, который не совсем в духе шаблона посредника.

понимает также, что рамки .NET имеют эквиваленты API Event VB6 в хотя реализуются по-разному (делегаты, и т.д.)

+0

Это известно как шаблон посредника, который стоит добавить к тексту этого ответа. – AnthonyWJones 2008-11-06 10:20:43

3

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

Относительные экологические проблемы, память, которую вы выделяете в системе типа VB6, обычно очищается для вас. Я говорю о вещах, которые вы назначаете с помощью ключевого слова New. Но есть значительное исключение, на которое указывает rpetrich и другие:

Из-за механизма подсчета ссылок, который VB использует для управления временем жизни выделенных объектов, возможно утечка памяти, если у вас есть циклические ссылки. Например, A-> B-> C-> A. Если у вас такой сценарий, вам, вероятно, нужно будет определить его самостоятельно и вылечить, явно указав ссылки на Nothing. Я не знаю каких-либо инструментов, которые очень помогают в определении этой проблемы.

Дополнительные проблемы возникают, когда вы используете библиотеки, написанные на других языках. Вы можете создать новый объект COM, написанный на C++, который выделяет некоторую внутреннюю память и обнаруживает, что вам нужно вызвать конкретный метод (например, «Закрыть»), чтобы освободить эту память. Возможно, такой COM-объект будет плохо написан, но их много.

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

  1. Постарайтесь узнать как можно больше о поведении каких-либо библиотек, которые вы используете, и
  2. Всегда запускать свой код во время просмотра памяти отслеживать в Performance Monitor, чтобы убедиться, что его использование памяти не растет неограниченным образом.
  3. Try, чтобы быть в курсе циклическое ссылки ;-)
+0

Так как VB6 (и СОМЫ в целом) используют подсчет ссылок, можно течь объекты через круговой Рекомендации. Вы должны отредактировать свой второй абзац, чтобы отразить это. – rpetrich 2008-11-05 18:15:03

3

Да, у меня были проблемы simmilar с различными формами, поэтому я им явно ни к чему на каждой выгрузке.

Но проблемы, когда в основном с сторонними элементами управления, кажется, что иногда не все COM-ссылки, где очищается правильно.

Посмотрите here.