这是我不明白的一个。
鉴于此类模块(剥离到重现崩溃所需的最低限度):
VERSION 1.0 CLASS
BEGIN
MultiUse = -1 'True
END
Attribute VB_Name = "TestCrashClass"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
Option Explicit
Public Function Init() As TestCrashClass
Attribute Init.VB_UserMemId = 0
Dim tcc As New TestCrashClass
Set Init = tcc
End Function
Public Property Get Data() As String
Data = "test data"
End Property
当我输入此代码时,有人能告诉我为什么Excel完全崩溃了:
Sub MakeExcelCrash()
With TestCrashClass(
此时,我发出了这条可爱的信息:
即使我在没有违规括号的情况下输入完整的程序,然后尝试稍后添加它们,我也会遇到同样的崩溃。
我能让Excel不崩溃的唯一方法是将一组()
从其他地方复制/粘贴到这行代码中。
Sub MakeExcelCrash()
With TestCrashClass()
Debug.Print .Data
End With
End Sub
如果Init()
方法有一个参数 - 甚至是一个可选参数 - 它在键入开始参数时不会崩溃。
我对为什么发生这种情况比对周围的方式更感兴趣;它实际上并没有经常出现在我的代码中,当它发生时,我可以通过改变方法来修复它,但我真的很沮丧,因为我不知道是什么造成了什么这些崩溃。那么也许有更多了解VBA内部工作的人可以向我解释一下吗?
答案 0 :(得分:11)
您甚至不需要With
块。 任何尝试在类名称关闭Excel后键入(
。
问题是您将VB_PredeclaredId
设置为true并且默认成员正在尝试返回自身。将调试器附加到垂死的Excel实例时,您可以看到基础问题是堆栈溢出:
EXCEL.EXE中0x0F06EC84(VBE7.DLL)处的未处理异常:0xC00000FD: 堆栈溢出(参数:0x00000001,0x00212FFC)。
当您键入With TestCrashClass(
时,会发生什么情况是VBA开始在默认属性上查找 索引器 ,因为Init()
没有有任何属性。例如,考虑Collection
。您可以使用默认属性的(Item
)索引器,如下所示:
Dim x As Collection
Set x = New Collection
x.Add 42
Debug.Print x(1) '<--indexed access via default member.
这与Debug.Print x.Items(1)
完全相同。这是您开始遇到问题的地方。 Init()
没有参数,因此VBA开始向下钻取默认成员以查找第一个具有索引器的成员,以便IntelliSense可以显示参数列表。它开始这样做:
x.[default].[default].[default].[default].[default]...
在您的情况下,它会创建一个无限循环,因为[default]
返回 x
。同样的事情发生在上面的Collection
代码中(除了它找到一个):
抛出你有一个默认实例的事实,最终结果是这样的:
Private Sub Class_Initialize()
Class_Initialize
End Sub
答案 1 :(得分:9)
正如@TimWilliams所指出的,拥有一个默认成员,它返回相同类的实例(或类循环,例如。ParentClass.ChildClass.ParentClass.ChildClass...
,其中ParentClass和ChildClass都有默认成员),当在某些语法情况下使用时,例如With
块,将导致VBE尝试解析默认成员。
第一个括号使得VBE假定必须有一个方法,索引get
或将接受参数的数组索引,因此它会启动以解析最终目标成员。
所以不完整的行,光标位于括号后面:
With TestCrashClass(
实际上与:
相同With TestCrashClass.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init '....You're inquisitive scrolling this far over, but you get the point.
在某些时候,你的系统或VBE耗尽了资源,并以热核团队的拥抱和优势退出。
+1用括号副本/面食即兴创作。
答案 2 :(得分:-4)
听起来像某种腐败。我之前有过这样的非理性行为,通常在大型项目中,并且解决它的唯一方法是将所有类等拖到新项目中。
我怀疑它发生是因为Excel没有真正删除已删除的类,模块,工作表等。你可以告诉这个因为文件大小。
没有Compact和Repair功能,就像在Access中一样,据我所知