• ベストアンサー

OCXからのコールバックを繰り返すとスタック領域が不足する

こんにちは。 いつもお世話になっております。 OCXからのコールバックが繰り返された場合に「実行時エラー28 スタック領域が不足しています。」が発生して困っています。 以下のようにOCXからのコールバックでプロシージャを再帰的に呼び出しています。 <Command1_Clickイベント> ------------------------------------------------------------------------------------- Private Sub Command1_Click() 'OnTestイベントを発生させる Test.Test End Sub ------------------------------------------------------------------------------------- <OnTestイベント> ------------------------------------------------------------------------------------- Private Sub Test_OnTest(ByVal sStatus As Long, ByVal FileName As String) Select Case sStatus Case 0 'ステータスが0になったら終了 Exit Sub Case Else '再帰的にOnTestイベントを発生させる Test.Test End Select End Sub ------------------------------------------------------------------------------------- すると、294回目でスタック領域不足が発生します。 MSDNによると「イベント連鎖」と呼ばれるものであるようですが、途中までうまくいくので何か他に原因がないかと思っています。 http://msdn2.microsoft.com/ja-JP/library/0ctsw64a.aspx 回避策などありましたらご教示下さい。 ちなみにOCXの処理としては、フォルダ内の該当ファイル名を1つずつ返すというものです。 <環境> Windows 2000, VB6.0

質問者が選んだベストアンサー

  • ベストアンサー
  • chie65536
  • ベストアンサー率41% (2512/6032)
回答No.2

文字通り、スタック領域を増やすしかありません。 イベント連鎖は関係ありません。 関数から自分自身を再帰的に呼ぶと、 ・値渡しされた引数 ・関数内で定義したローカル変数 ・関数内で確保された動的領域(String型変数などの実体) ・VBが暗黙的に作成する見えない作業変数(String型同士を連結した結果文字列など) ・関数から抜けた時に呼び出し元に戻るべき場所 ・イベントが終了して元の地点に戻るべき場所 を、すべてスタック領域に保存し、関数から抜けるまで保持し続けます。 再帰を5段階行う(関数から抜ける事なく、自分自身を5回呼ぶ)と、上記の内容が5つ分、スタックに上積みされます。 もし、スタック領域が全体で512キロバイトで、1段分に4キロバイト消費すると仮定すると、512÷4=128で、128階層まで深くなると破綻し、スタック領域不足が出ます。

sputnik8823
質問者

お礼

chie65536さん、コメントありがとうございます。 もともとのOCXの設計、もしくは使用方法に問題があったのですね。 スタック領域を増やす事はできないので、別の方法でファイルを取得するようにしました。

その他の回答 (1)

  • SUPER-NEO
  • ベストアンサー率38% (706/1857)
回答No.1

イベントはマルチスレッドで動作するので、 これが「イベントの連鎖」として異常を起こしている、 と考えられます。 ですから、コード上でイベント実行中にイベントを起動しない、 という動きにするなどの対策が必要です。

sputnik8823
質問者

お礼

SUPER-NEOさん、コメントありがとうございます。 イベント実行中にイベントを実行しないことで解決しました。

関連するQ&A

  • コールバックでイベントを使うメリットは何でしょうか

    コールバック関数を実行するのに、わざわざイベントを使う利点は何でしょうか。 下記のコードでは、どちらでも大して変わらないように見えますが・・・ Module modMain Sub Main() Dim myRaise As clsMyRaiseEvent = New clsMyRaiseEvent 'イベントを使った使用法 AddHandler myRaise.MyEvent, New clsMyRaiseEvent.dlgMyEvent(AddressOf MyCallBack) myRaise.Test1() '関数ポインタ的な使用法 myRaise.callback = New clsMyRaiseEvent.dlgMyEvent(AddressOf MyCallBack) myRaise.Test2() Console.ReadLine() End Sub 'コールバック関数 Private Sub MyCallBack(ByVal aEx As Exception) Console.WriteLine("Called") End Sub End Module Public Class clsMyRaiseEvent Public Delegate Sub dlgMyEvent(ByVal aEx As Exception) Public Event MyEvent As dlgMyEvent 'デリゲート型のイベント Public callback As dlgMyEvent Public Sub Test1() RaiseEvent MyEvent(New Exception) End Sub Public Sub Test2() callback(New Exception) End Sub End Class

  • Call文 でデバックできません。

    VB初心者です。 Win2003Sarver+SQL2000+VB.Net2008の組合せで作っています。 Call文で下記の様にすると Private Sub Button自動1600_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button自動1600.Click Call Button1600_Click() <--ここでデバックできません。 End Sub Private Sub Button1600_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1600.Click Me.洗浄機記録BindingSource.AddNew() Me.日付TextBox.Text = Now End Sub Call Button1600_Click() デバックできません。 下記の様にすると動きます。 Private Sub Button自動1600_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button自動1600.Click Call B1600() End Sub Private Sub B1600 Me.洗浄機記録BindingSource.AddNew() Me.日付TextBox.Text = Now End Sub Call先に Click(ByVal sender As System.Object, ByVal e As System.EventArgs) が あると引数か何かが必要になるのでしょうか。 ご存知の方教えてください。

  • 教えてください。Visual Basic 2010

    教えてください。Visual Basic 2010で電卓でわからないところ Visual Basic 2010で四則演算ができる簡易電卓を 作っています。 下のソースは+,-.×,÷のボタンが押された時の処理なのですが、 3+6-3の計算が、0になってしまします 3+6-の時点で-3と表示されてしまいます。 str1は最初に入力された数値が保存されています。 Private Sub ButtonAdd_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonAdd.Click flag = 1 Call kei() End Sub Private Sub ButtonSub_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonSub.Click flag = 2 Call kei() End Sub Private Sub ButtonMul_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonMul.Click flag = 3 Call kei() End Sub Private Sub ButtonDiv_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonDiv.Click flag = 4 Call kei() End Sub Private Sub kei() Dim c1 As Single If IsNumeric(str1) = True Then c1 = CSng(str1) Else Exit Sub End If str1 = "" Select Case flag Case 1 anser = anser + c1 Case 2 anser = anser - c1 Case 3 anser = anser * c1 Case 4 If c1 = 0 Then Exit Sub anser = anser / c1 Case Else anser = c1 End Select TextBox1.Text = CStr(anser) flag = 0 End Sub

  • VBA スタック容量が足りない・・・

    こんばんわ! エクセルのVBAを使った管理システムを作ろうと思うのですが、色々考えて下記のような状態にしてみたのですが、ユーザーフォームをモードレスにするとスタック容量が足りなくなります。 Sub aaa_date() If Range("a1") = 1 Then bbb_date.Show ElseIf Range("a1") = 2 Then ccc_date.Show ElseIf Range("a1") = 3 Then ddd_date.Show End If Call aaa_date End Sub bbb_date(ユーザーフォーム)に↓ Private Sub CommandButton1_Click() Range("a1") = 2 Unload Me End Sub Private Sub CommandButton2_Click() Range("a1") = 3 Unload Me End Sub ccc_date(ユーザーフォーム)に↓ Private Sub CommandButton1_Click() Range("a1") = 1 Unload Me End Sub Private Sub CommandButton2_Click() Range("a1") = 3 Unload Me End Sub ddd_date(ユーザーフォーム)に↓ Private Sub CommandButton1_Click() Range("a1") = 1 Unload Me End Sub Private Sub CommandButton2_Click() Range("a1") = 2 Unload Me End Sub ※bbb_dateとccc_dateとddd_dateはそれぞれにあるボタンを押すとA7セルの値を変更するようにして、aaa_dateでどのフォームを表示するのかを選択しています。 ※実際にはもっと沢山ユーザーフォームがあります。 上記の状態では動作するのですが、エクセルの表に値を入力したいので、bbb_dateとccc_datとddd_datをvbModeless(モードレス状態)にすると、スタック容量が足りませんと出ます。 別のやり方でもよいですので、ユーザーフォームを切り替える良い方法があったらお願いします。

  • VBAエラー「スタック領域が不足しています」

    C2とD2のセルに英文字を入力した時,先頭文字を大文字にするVBAを組んだのですが,いざ実行すると「スタック領域が不足しています」と出てしまいます。以下にコードを示します。 'Sheet1 Option Explicit Private Sub Worksheet_Change(ByVal Target As Range)   If Target.Row = 2 And Target.Column = 3 Then     Range("C2").Value = StrConv(Range("C2").Value, vbProperCase)   End If   If Target.Row = 2 And Target.Column = 4 Then     Range("D2").Value = StrConv(Range("D2").Value, vbProperCase)   End If End Sub なぜこのようなエラーが出るのでしょうか。考えれば考えるほど合っているように思えて仕方なくなったので,ミスがあればご指摘をおねがいします。

  • VB6.0でPowerPoint上のイベントを取得したい

    VB6.0からPowerPointのファイルを開き、 PowerPoint上のイベントを取得したいのですが、 方法が分からず困っております。 具体的には、ツールバーのプレビューボタンが クリックされたことをVBで検知したいと考えています。 現状では下記のように、Applicationの閉じるイベントは 取得できたのですが、そこからどうして良いか分からない状態です。 良きアドバイスをお願い致します。 ---------------------------------------------------- Option Explicit Private WithEvents PPTApp As PowerPoint.Application '■パワポを開く Private Sub Command1_Click() Set PPTApp = New PowerPoint.Application PPTApp.Visible = True PPTApp.Presentations.Open (App.Path & "\test.ppt") End Sub '■パワポを閉じる Private Sub Command2_Click() PPTApp.Quit Set PPTApp = Nothing End Sub '■閉じるイベントを取得 Private Sub PPTApp_PresentationClose(ByVal Pres As PowerPoint.Presentation) MsgBox "閉じる" End Sub ----------------------------------------------------

  • Access2013でスタック領域不足エラー

    Access2013でスタック領域不足エラー お世話になっております。 Access2013で開発したシステムを現在Office365で修正を行っております。 親フォーム(連結フォーム)に「次へ」ボタンを配置し、クリックする度に次のレコードをフォーム上に表示するプログラムで、「スタック領域が不足しています」のエラーが発生します。 ゆっくりとレコードを送る分には問題ないのですが、ボタンを早くクリックし続けると、3,40件あたりでエラーとなります。 また、親フォームの中に8つのタブを作り、それぞれサブフォームを作成し、親フォームのIDとサブフォームのIDでリンクしており、次へいくたびに該当のデータを表示しております。 おそらくこのタブでの表示処理が多いためエラーとなっていると推測しております。 「次へ」ボタンのコードは以下の通りです。 Private Sub bt_next_Click() On Error Resume Next DoCmd.GoToRecord , , acNext End Sub 色々と調べておりますがなかなか解決しません。 何か良い対策はございませんでしょうか。

  • 標準モジュールとイベントの質問

    初めて質問します。 ビジュアルベーシックで標準モジュールで ボタンのクリックイベントを実行したいのですが どうやってプログラムすればいいんでしょうか? 今の会社に入っていきなりVBの仕事させられて とっても困っています。 Private Sub Frm1Command1_Click() Call Module1.Frm1Command1_Click End Sub こんな書き方じゃなくて、標準モジュール内で Public Sub Command1_Click() MsgBox "sine" End Sub って書いて実行できるようにしなくてはダメなんです。 どうすればいいんでしょうか? もしかして無理なんでしょうか? これ、上司の嫌がらせだったらイヤですね・・・。

  • サブルーチンの使い方

    こんにちは 以前 このサイトでサブルーチンを教えて頂いたのですが 今回は、このサブルーチンを使って Commandbuttonに Sheets("20年7月度").Cells(2, 6).Value = Cells(2, 6) & Mojiを 入れたいのですが、どのようにすれば いいですか? 宜しくお願い致します。 Private Sub mySub(Moji) '数字 If Me.MultiPage1.Value = 0 Then TextBox3.Value = TextBox3 & Moji Else: TextBox1.Value = TextBox1 & Moji End If End Sub Private Sub CommandButton1_Click() 'サブルーチン Call mySub("1") End Sub Private Sub CommandButton2_Click() Call mySub("2") End Sub Private Sub CommandButton3_Click() Call mySub("3") End Sub Private Sub CommandButton4_Click() Call mySub("4") End Sub Private Sub CommandButton5_Click() Call mySub("5") End Sub Private Sub CommandButton6_Click() Call mySub("6") End Sub Private Sub CommandButton7_Click() Call mySub("7") End Sub Private Sub CommandButton8_Click() Call mySub("8") End Sub Private Sub CommandButton9_Click() Call mySub("9") End Sub Private Sub CommandButton10_Click() Call mySub("0") End Sub Private Sub CommandButton11_Click() Call mySub("00") End Sub Private Sub CommandButton12_Click() Call mySub("000") End Sub

  • スタック領域エラーについて

    いつも参考にさせていただいています。 ご回答よろしくおねがいします。 新規のフォームにチェックボックスを3つ追加しました。 コントロール配列です。 ------frame1-------- | checkbox1(0) | | checkbox1(1) | | checkbox1(2) | -------------------- このときに、 --------------------------------------------- Private Sub Check1_Click(Index As Integer) Check1(0).Value = 0 Check1(1).Value = 0 Check1(2).Value = 0 Check1(Index).Value = 1 End Sub --------------------------------------------- 以上のようにプログラムを実行すると、 スタック領域エラー(エラー28)が出力されます。 この回避方法について、また原因がおわかりいただけたら ご教授おねがいできないでしょうか? OS:WinXP SP3 環境:VB6