У нескольких разработчиков в моей команде есть эта проблема. Мы можем запустить наше приложение в среде IDE нормально, но когда мы в конечном итоге выйдем из приложения, тогда сама IDE выйдет из строя.
Авария принимает форму
"Visual Basic has stopped working"
Не имеет значения, закрываем ли мы приложение корректно или принудительно останавливаем его в отладчике; тот же результат (разбился IDE).
Последовательность выхода для приложения:
Пользователь выбирает «выход» из меню
Обработчик событий меню вызывает Unload Me
Срабатывает обработчик событий Form_QueryUnload
Срабатывает обработчик событий Form_Unload
. Оно делает:
'close all sub forms
For i = Forms.Count - 1 To 1 Step -1
Unload Forms(i)
Next
Затем сохраняет некоторые данные, а затем выполняет Exit Sub
.
Мы обычно запускаем групповой файл, в котором содержится 5-6 проектов.
Иногда кажется, что эта ошибка исчезает, а иногда возникает случайным образом. Не знаю, какой фактор на это влияет.
Если мы на самом деле не запускаем приложение, а только IDE, тогда оно работает нормально, и мы можем выйти из самой IDE в обычном режиме.
Кто-нибудь видел это раньше? Любые идеи? Спасибо!
Вы используете в проекте хуки API любой для сообщений Windows? Если это так, убедитесь, что они используются только в скомпилированном приложении нет в среде IDE.
Можете ли вы поделиться своим кодом выхода?
FWIW, мне также интересно, что у вас есть «команда» разработчиков VB6. На самом деле приятно это слышать.
Это наиболее определенно вызвано утечками объектов VB6, которые участвуют в создании подклассов / подключений, и не только ими.
Чтобы избавиться от этих сбоев, мы оснастили все наши классы (включая формы, пользовательские элементы управления, конструкторы и все, что может быть создано) вызовами DebugInstanceInit
и DebugInstanceTerm
в соответствующих событиях Class / Form / UserControl Initialize
и Terminate
.
Public Sub DebugInstanceInit(sModuleName As String, sDebugID As String, oObj As Object)
Public Sub DebugInstanceTerm(sModuleName As String, sDebugID As String)
Они в основном отслеживают в любое время, сколько и какие экземпляры использует приложение. Каждому экземпляру назначается уникальный sDebugID
в DebugInstanceInit
, который используется в качестве ключа в коллекции DebugIDs
. Эта коллекция создается пустой в Sub Main
, и когда приложение завершается (то есть в Form_Unload
основной формы), эта коллекция должна быть пустой или с фиксированным количеством оставшихся экземпляров (например, ровно 4), в противном случае ее содержимое является типом объектов, которые мы утекаем.
Что исправило сбои в IDE?
Обратите внимание, что коллекция создается так поздно, как Sub Main
, что означает, что она должна оставаться Nothing
во время разработки. Просто поставим простую проверку в DebugInstanceInit
вот так
If DebugIDs Is Nothing Then
If Left$(sModuleName, 3) <> "ctx" Then
DebugPrint "DebugInstanceInit", "mdErrorHandling", sDebugID & " " & LIB_NAME & "." & sModuleName & "." & FUNC_NAME_INITIALIZE & " (This should not happen)"
End If
Else
...
End If
В основном это предотвращало создание экземпляров что-нибудь, отличных от необработанных пользовательских элементов управления, размещенных в формах, во время разработки. Сюда входят объекты GlobalMultiUse
, сюда входят все, к чему имеют доступ свойства UC, поскольку свойства UC - это своего рода процедуры, к которым, безусловно, осуществляется доступ во время разработки.
Поэтому нам пришлось сильно опрыскать большую часть кода UC проверками Ambient.UserMode
, подобными этой
If Ambient.UserMode Then
Set .Picture = LoadStdPicture(ucsPicHelp)
End If
Оказалось, что наша глобальная функция LoadStdPicture
, например, создавала экземпляр некоторого cDibSections
. Приятно то, что как только вы устанавливаете точку останова в операторе отладочной печати (This should not happen)
, стек вызовов показывает вам именно вызывающее свойство нарушающего UC.
Я думаю, что этот ответ был правильным - оказалось, что проблема в моей конкретной программе возникла из сторонней библиотеки OCX; когда я обновил его до более новой версии, проблема была решена. Спасибо, что наставили меня на правильный путь.
Также - я заметил несколько других подобных сообщений, которые вы сделали по этой теме, но я не уверен, включает ли какое-либо из них весь исходный код ваших очень полезных процедур DebugInstance ... (). Возможно, если вы добавите их сюда (или ссылку на полные источники), это будет полезно!
@DaveInCaz Это может быть так же просто, как сгенерировать следующий последовательный идентификатор отладки и добавить информацию об экземпляре в коллекцию с "#" & sDebugID
в качестве ключа (два LoC), а затем просто удалить ключ "#" & sDebugID
при завершении (один LoC). Лучшим примером был бы целый проект с инструментальными классами и формами и msgbox с сообщением об утечках при разрыве приложения. . .
Я считаю, что другой ответ правильно в своей технической оценке причины проблемы. Но также может быть полезно кратко описать процедуру, которую я использовал для сужения строк исходного кода. В моем случае эта проблема оказалась СОВЕРШЕННО случайной, поэтому было трудно понять, с чего начать.
Мой подход был не ракетостроением - скорее грубой силой. По сути, я использовал двоичный поиск, чтобы исключить / исключить участки кода. Первым шагом было закомментировать всю процедуру запуска, чтобы приложение запускалось как пустая оболочка; это продемонстрировало, что проблема исчезла (нулевой результат).
После этого я рекурсивно прокомментировал примерно половину кода, каждый раз проверяя проблему. Каждый блок оценивался как логическое значение - это либо создавало, либо не создавало проблемы. Затем продолжайте снова в блоке, который не исключен.
В конце концов (и быстрее, чем я ожидал) это привело к единственной строке кода, которая обращается к свойству стороннего элемента управления.
Я тоже видел это. Не очень часто и вроде бы случайно, как и вы. Я тоже не нашел решения.