2017-02-06 16 views
9

ここにはわかりません。 (クラッシュを再現するために必要な最低限にストリップダウン)このクラスモジュールを考える 開いた括弧を入力すると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 

私はこのコードで入力するとExcelが完全にアウトクラップス、なぜ誰も教えてもらえます:

Sub MakeExcelCrash() 
    With TestCrashClass(
この時点で

、Iこの素敵なメッセージ:

Excel crash - oops!

括弧を付けずに完全な手順を入力して後で追加しようとしても、同じクラッシュが発生します。

Excelをクラッシュさせないようにする唯一の方法は、このコード行に()のセットをコピーして貼り付けることです。

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

Init()方法がある場合は、パラメータを-でも、オプション1 - それは開口部の括弧が入力されたときにクラッシュすることはありません。

なぜ私はについてもっと興味がありますか?なぜこれが起こるのですか?それは実際に私のコードで頻繁に起こることはありませんし、私はそれを修正することができますが、私はアプローチの変化でそれを修正することができますが、私は本当にこれらのクラッシュを引き起こしているのか分からない。 VBAの内部作業についてもっと知っている人は、私にそれを説明することができますか?

+0

入力中にExcelが何らかの自動補完機能を提供していますか? – Carcigenicate

+0

私はあなたのクラスのインスタンスを作成するメソッドを作成すると、デフォルトメソッドが無限ループを作成していると思います。おそらく、その行をタイプするときにクラスのコードが評価されている可能性があります...そのメソッドの目的は何ですか? –

+2

あなたは 'Init'をデフォルトのメンバーにしたので、VBEはそれに基づいてIntellisenseのドロップダウンをしようとします - それが無限ループに入るとすぐに(' Init'は同じクラスの別のインスタンスであり、同じ既定のメンバでも同様です)...そしてExcelがクラッシュします。 –

答えて

9

Withブロックは必要ありません。 は、クラス名の後に(と入力するとExcelがダウンします。

問題は、VB_PredeclaredIdがtrueに設定されていて、デフォルトメンバーが自身を返そうとしていることです。

0x0F06EC84 EXCEL.EXE中(VBE7.DLL)で

未処理の例外:0xC00000FD: スタックオーバーフロー(パラメータあなたが死んでExcelのインスタンスにデバッガをアタッチするときは、根本的な問題は、スタックオーバーフローであることがわかります:0x00000001,0x00212FFC)。

あなたがWith TestCrashClass(を入力すると、何が起こるかはInit()はどんな性質を持っていないため、VBAには、デフォルトプロパティのインデクサーを探してを開始することです。たとえば、Collectionとします。

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)とまったく同じです:あなたはこのように、デフォルトのプロパティの(Item)インデクサーを使用することができます。ここで問題にぶつかり始めるのです。 Init()にはパラメータがないため、VBAは既定のメンバをドリルダウンしてインデクサを持つ最初のものを検索し、IntelliSenseでパラメータリストを表示できます。それは、このやって起動する:あなたのケースでは

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

を、それが[default]戻りxので、無限ループを作成しています。 (それが見つかる除いて)同じことは、上記のCollectionコードで起こる:

Private Sub Class_Initialize() 
    Class_Initialize 
End Sub 
:既定のインスタンスを持っており、最終的な結果は、このようなものであるという事実で

IntelliSense on open parens

スローを

+0

OK、それは意味があります。詳細をありがとう。 –

-4

何らかの腐敗のような音です。私はこれまで、大規模なプロジェクトではExcelのような不合理な振る舞いをしていましたが、それを回避する唯一の方法は、すべてのクラスなどを新しいプロジェクトにドラッグすることです。

Excelは、削除されたクラス、モジュール、ワークシートなどを実際には削除しないため、これが起こると思われます。ファイルサイズのためにこれを知ることができます。

全く最適化と修復機能は、私の知る限り

+0

まったく新しいプロジェクトでも同様のことが起こります。 –

7

として@TimWilliamsが同じクラスのインスタンスを返すデフォルトのメンバーを持つ、指摘承知しているように、Accessのように、存在しない(またはたとえば、ParentClass.ChildClass.ParentClass.ChildClass...の場合、ParentClassとChildClassの両方にデフォルトメンバーがあります)、Withブロックなどの特定の構文で使用すると、VBEはデフォルトのメンバーを解決します。

最初のかっこでは、引数を取るインデックスgetまたは配列インデックスが必要であるとVBEが想定しているため、最終的なターゲットメンバーを解決するためにオフに設定されます。

だから、括弧の後に配置されたカーソルで不完全ライン、:

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

熱核グループの抱擁は私の+1を得ます –

+2

私は右にずっとスクロールして、どれくらいの距離をとるのかを知る必要があります。ありがとう! –

関連する問題