这是我不明白的一个.
鉴于此类模块(剥离到重现崩溃所需的最低限度):
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
Run Code Online (Sandbox Code Playgroud)
任何人都可以告诉我为什么当我输入以下代码时Excel完全崩溃:
Sub MakeExcelCrash()
With TestCrashClass(
Run Code Online (Sandbox Code Playgroud)
在这一点上,我这个可爱的消息:
即使我输入一个没有违规括号的完整程序然后尝试添加它们,我也会遇到同样的崩溃.
我能让Excel不崩溃的唯一方法是将一组()从其他地方复制/粘贴到这行代码中.
Sub MakeExcelCrash()
With TestCrashClass()
Debug.Print .Data
End With
End Sub
Run Code Online (Sandbox Code Playgroud)
如果该Init()方法具有参数 - 甚至是可选参数 - 它在键入开始paren时不会崩溃.
我更好奇为什么会发生这种情况而不是围绕它的方式; 它实际上并没有出现在我的代码中,当它发生时,我可以通过改变方法来修复它,但我真的很沮丧,因为我不知道是什么导致了这些崩溃.那么也许有更多了解VBA内部工作的人可以向我解释一下吗?
Com*_*ern 11
你甚至不需要With块. 任何(在类名后面输入的尝试都会使Excel失效.
问题是您将VB_PredeclaredIdset设置为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.
Run Code Online (Sandbox Code Playgroud)
这完全等同于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
Run Code Online (Sandbox Code Playgroud)
正如@TimWilliams指出的那样,拥有一个返回同一个类的实例的默认成员(或类循环,例如ParentClass.ChildClass.ParentClass.ChildClass...,ParentClass和ChildClass都有默认成员),并且在某些语法情况下使用时,例如With块,将导致VBE尝试解析默认成员.
第一个括号使VBE假定必须有一个方法,索引get或数组索引将接受一个参数,因此它将启动以解析最终目标成员.
所以不完整的行,光标位于括号后面:
With TestCrashClass(
Run Code Online (Sandbox Code Playgroud)
实际上是有效的:
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.
Run Code Online (Sandbox Code Playgroud)
在某些时候,你的系统或VBE耗尽了资源,并以热核团队拥抱的优雅和平衡退出.
用括号副本/面食即兴创作+1.
| 归档时间: |
|
| 查看次数: |
265 次 |
| 最近记录: |