Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Excel crash when typing open parenthesis

Tags:

excel

vba

vbe

Here's one I don't understand.

Given this class module (stripped down to the bare minimum necessary to reproduce the crash):

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

Can anyone tell me why Excel totally craps out when I type in this code:

Sub MakeExcelCrash()
    With TestCrashClass(

At this point, I this lovely message:

Excel crash - oops!

Even if I type in a full procedure without the offending parentheses and then try to add them later, I get the same crash.

The only way I can get Excel not to crash is to copy/paste a set of () from somewhere else to this line of code.

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

If the Init() method has a parameter—even an optional one—it won't crash when the opening paren is typed.

I'm more curious about why this happens than ways around it; it doesn't actually come up that often in my code and when it does I can fix it with a change in approach, but I'm really frustrated that I don't know what's causing these crashes. So maybe someone who knows more about the inner working of VBA can explain it to me?

like image 492
Patrick Wynne Avatar asked Feb 06 '17 19:02

Patrick Wynne


1 Answers

You don't even need the With block. Any attempt to type ( after the class name takes Excel down.

The problem is that you have the VB_PredeclaredId set to true and the default member is trying to return itself. When you attach a debugger to the dying Excel instance, you can see that the underlying issue is a stack overflow:

Unhandled exception at 0x0F06EC84 (VBE7.DLL) in EXCEL.EXE: 0xC00000FD: Stack overflow (parameters: 0x00000001, 0x00212FFC).

When you type With TestCrashClass(, what happens is that VBA starts looking for an indexer on the default property, because Init() doesn't have any properties. For example, consider a Collection. You can use the default property's (Item) indexer like this:

Dim x As Collection
Set x = New Collection
x.Add 42
Debug.Print x(1)   '<--indexed access via default member.

This is exactly equivalent to Debug.Print x.Items(1). This is where you start running into problems. Init() doesn't have parameters, so VBA starts drilling down through the default members to find the first one that has an indexer so IntelliSense can display the parameter list. It starts doing this:

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

In your case, it's creating an infinite loop because [default] returns x. The same thing happens in the Collection code above (except it finds one):

IntelliSense on open parens

Throw in the fact that you have a default instance, and the end result is something like this:

Private Sub Class_Initialize()
    Class_Initialize
End Sub
like image 147
Comintern Avatar answered Oct 01 '22 07:10

Comintern