input左括号时,Excel崩溃

这是我不明白的一个。

鉴于这个类模块(剥离到最低限度重现崩溃):

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 

任何人都可以告诉我为什么当我input这个代码时,Excel为什么总是出来:

 Sub MakeExcelCrash() With TestCrashClass( 

在这一点上,我这个可爱的消息:

Excel崩溃 - 哎呀!

即使我input完整的程序而没有违规的括号,然后尝试稍后添加它们,我也会遇到相同的崩溃。

我可以让Excel不会崩溃的唯一方法是从其他位置复制/粘贴一组()到这行代码。

  Sub MakeExcelCrash() With TestCrashClass() Debug.Print .Data End With End Sub 

如果Init()方法有一个参数 – 即使是一个可选的参数 – 当打开paren时,它不会崩溃。

我更好奇为什么会发生这种事情,而不是周围的方式。 在我的代码中实际上并没有经常出现这种情况,当我可以通过改变方法来修复它时,我真的很沮丧,我不知道是什么导致了这些崩溃。 所以也许有人对VBA的内部工作有更多的了解可以向我解释一下?

你甚至不需要With块。 任何types的尝试(在类名称之后将Excel取下。

问题是你有VB_PredeclaredId设置为true,并且默认成员试图返回自己。 当您将debugging器附加到垂死的Excel实例时,可以看到底层问题是堆栈溢出:

EXCEL.EXE中的0x0F06EC84(VBE7.DLL)未处理的exception: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开始向下钻取默认成员以find第一个具有索引器的参数,这样IntelliSense可以显示参数列表。 它开始这样做:

x.[default].[default].[default].[default].[default]...

在你的情况,这是创build一个无限循环,因为[default] 返回 x 。 同样的事情发生在上面的Collection代码中(除了它find一个):

智能感知打开的parens

抛出事实,你有一个默认的实例,最终的结果是这样的:

 Private Sub Class_Initialize() Class_Initialize End Sub 

正如@TimWilliams所指出的那样,有一个默认成员返回一个相同类的实例(或者一个类循环,例如, ParentClass.ChildClass.ParentClass.ChildClass... ,其中ParentClass和ChildClass都有默认成员),并且当在某些语法情况(如With块)将导致VBE尝试并parsing默认成员。

第一个括号使得VBE假设必须有一个方法,索引get或数组索引,它将接受一个参数,所以它开始parsing最终的目标成员。

所以这个不完整的行,光标位于括号之后:

 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用于即兴表演与一对圆括号的复制/面食。

听起来像是某种腐败。 我曾经使用Excel的行为不像以前那样,通常在大型项目中,解决这个问题的唯一方法就是把所有的类拖放到一个新的项目中。

我怀疑这是因为Excel并没有真正删除已被删除的类,模块,工作表等。 你可以告诉这个,因为文件的大小。

据我所知,没有紧凑和修复function,就像在Access中一样