我团队中的几个开发人员都有此问题。我们可以在IDE中正常运行应用程序,但是最终退出该应用程序时, IDE本身将崩溃。
崩溃采用
的形式“ Visual Basic停止工作”
我们好好退出应用程序还是在调试器中强制停止它并不重要;相同的结果(崩溃的IDE)。
该应用的退出顺序为:
用户从菜单中选择“退出”
菜单事件处理程序调用{{1}}
Unload Me
事件处理程序触发
Form_QueryUnload
事件处理程序将触发。它确实:
Form_Unload
然后保存一些数据,然后执行'close all sub forms
For i = Forms.Count - 1 To 1 Step -1
Unload Forms(i)
Next
。
我们倾向于运行一个包含5-6个项目的组文件。
此错误有时似乎消失了,有时甚至是随机出现的。我不知道是什么因素影响了这一点。
如果我们实际上并没有运行应用程序,而只是运行IDE,那么它就可以正常运行,并且我们可以正常运行IDE。
有人看过吗?有任何想法吗?谢谢!
答案 0 :(得分:5)
这绝对是由子类化/挂钩中涉及的VB6对象泄漏引起的,而不仅仅是这些。
要摆脱这些崩溃,我们要做的是使用各个类中的DebugInstanceInit
和DebugInstanceTerm
调用来检测我们所有的类(包括表单,用户控件,设计器和任何可以实例化的东西) / 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
基本上,这可以防止在设计时实例化除放置在表单上的原始UserControl之外的任何其他内容。这包括GlobalMultiUse
对象,其中包括UC属性正在访问的任何内容,因为UC属性是在设计时肯定会访问的一种例程。
因此,我们不得不像这样Ambient.UserMode
的检查中大量使用UC的大部分代码
If Ambient.UserMode Then
Set .Picture = LoadStdPicture(ucsPicHelp)
End If
事实证明,我们的LoadStdPicture
全局函数正在实例化某些cDibSections
。令人高兴的是,一旦在(This should not happen)
调试打印语句上设置了一个断点,调用堆栈就会向您确切显示令人讨厌的UC的令人讨厌的属性。
答案 1 :(得分:0)
我相信another answer在对问题原因的技术评估中是正确的。但是,简要描述一下我用来缩小源代码行的过程可能也很有用。就我而言,这个问题似乎是完全随机的,因此很难知道从哪里开始。
我的方法不是火箭科学,而是蛮力。本质上,我使用二进制搜索来限制代码的入/出部分。第一步是注释掉整个启动过程,以便该应用程序以空壳启动。这表明问题消失了(无结果)。
在此之后,我递归地注释了大约一半的代码,每次都测试该问题。每个块都被评估为布尔值-它是否导致了问题。然后在不排除的块中再次进行。
最终(比我预期的更快),这导致了一行代码访问了第三方控件的属性。