[リストへもどる]   [VBレスキュー(花ちゃん)]
一括表示

投稿時間:2005/08/01(Mon) 17:39
投稿者名:エデン
URL :
タイトル:
分母が固定値なのに「0で除算」!?
VBアプリを開発していますが、以下のような現象に遭遇し、原因究明に手こずっています。
原因究明の手がかりを得たく、投稿させていただきました。よろしくお願いします。

まず、状況説明ですが、規模の大きいアプリケーションなので、関連しそうな部分だけを抜き出して
説明します。

(1)実行プラットフォームは Windows2000Pro.SP4, 開発環境は VB6 SP5

(2)GUIはMDI構成

(3)MDI子ウィンドウのうちの1つに、バーグラフを描画表示する自作のActiveXコンポーネントが貼っ
てあり、描画更新のタイマコントロールが同一のフォームに貼ってあり、このタイマイベントで0.5秒
ごとに描画更新します。また、複数ページ表示に対応させるため、「ページ送り」と「ページ戻り」
のボタンが同一のフォームに貼り付けてあります。表示用のActiveXコンポーネント自体は1つで、ボ
タンクリックによって表示させる内部データを切り替えて表示させる仕組みです。

(4)同一LAN上の別PCにデータを送信するため、MDIの親フォームにソケットコントロールとタイマコン
トロールを貼ってあります。データ送信先PCがソケットサーバ(Listen)、このアプリがクライアント
です。タイマーコントロールのタイマイベントで、5秒ごとに所定のフォーマットのバイナリデータを
送信します。

以上のような状況で以下のような現象が発生しました。

■バーグラフフォームのページ送り/戻りボタンを連打(1秒に2〜3回程度)すると、「あるタイミン
グ」で「実行時エラー'11': 0で除算しました。」のVBエラーが発生します(赤バッテンのダイアロ
グではありません)。VisualStudio からデバッグ実行してこのVBエラーを発生させ、[デバッグ]ボタ
ンでVBエラー発生ポイントのソースを見ると、決まって以下のプログラム行を指します。

stSocketFrame.bytDigAlarm(1) = CByte((nStatusData(0) And &HFF00) / &HFF)

これは、(4)で説明した、ソケット送信用タイマコントロールのTimerイベントのサブルーチンから
Callで呼ばれた、ソケット送信用データを作成する関数の中の1行です。 nStatusData()は 0〜1の2要
素のInteger型配列、Type で定義したstSocketFrameはソケット送信データ格納用の構造体で、
bytDigAlarm は 0〜1 の2要素のByte型配列です。

このままこの行からデバッグステップ実行すると、今度はVBエラーを起こすことなくそのまま実行さ
れ、連続実行すると何事もなくまたアプリが動きます。

VBエラーの起こる「あるタイミング」ですが、これまで調べた限りでは、ソケット送信のタイマイベ
ントと、バーグラフのページ送り/戻りボタンクリックによってバーグラフフォームを書き換える処理
が重なるようなタイミングで多く発生しているような傾向です。

それで、このソケット送信タイマコントロールのTimerイベントサブルーチンの1行目で、このタイマ
コントロールのEnableプロパティをFalseにし、Timerイベントサブルーチンの出口でEnableプロパテ
ィをTrueにして、ソケット送信のTimerイベントが重複起動されないようにすると、このVBエラーは起
きなくなります。

以上の内容から疑問点をまとめますと、

(A)なぜ分母固定値の割り算処理で「0で除算」などというVBエラーが起こるのか?
(B)一度VBエラーで止まった行がなぜステップ実行で再び正常に実行できるのか?
(C)ソケット送信タイマの重複起動を禁止すると、なぜVBエラーが出なくなるのか?

という3点です。特に分母が固定値の割り算処理で「0で除算」というVBエラーが出る原因が皆目見当
がつきません。

長文ですみませんが、よろしくお願いします。

投稿時間:2005/08/01(Mon) 21:10
投稿者名:のびた
Eメール:
URL :
タイトル:
Re: 分母が固定値なのに「0で除算」!?
考えられる原因としては、0の除算はそこではなく、別の場所で発生していると考えた方が
自然じゃないでしょうか?
>分母固定値の割り算処理で「0で除算」などというVBエラーが起こる
はありえないと思いますよ。それを再現できるコードを作成できれば原因も分かるでしょう。

一番怪しいのはActiveX内の処理じゃないでしょうか?

投稿時間:2005/08/02(Tue) 09:29
投稿者名:エデン
URL :
タイトル:
Re^2: 分母が固定値なのに「0で除算」!?
のびたさん、コメントありがとうございました。

> 考えられる原因としては、0の除算はそこではなく、別の場所で発生していると考えた方が
> 自然じゃないでしょうか?
> >分母固定値の割り算処理で「0で除算」などというVBエラーが起こる
> はありえないと思いますよ。それを再現できるコードを作成できれば原因も分かるでしょう。

そうですね。私もVBはじめとしてプログラムの経験は長いですが、こんなエラーは初めて見ました。
ありえないはずのエラーなので、どう対処すべきかで悩んでます。


> 一番怪しいのはActiveX内の処理じゃないでしょうか?

やはりそうですかね。
自作のActiveXコンポーネントが何か行儀の悪いことをやっているのかもしれません。
一度この辺りを疑ってじっくり原因を探ってみます。

アドバイスありがとうございました。

投稿時間:2005/08/02(Tue) 12:47
投稿者名:K.J.K.
Eメール:akiya@koalanet.ne.jp
URL :
タイトル:
Re: 分母が固定値なのに「0で除算」!?
VB6を長く使っているならばわかると思いますが、「0で除算」は
VBステートメントによるエラートラップではひっかからない例外を
VBランタイムが受け取ったときに生成する例外でもあります。

ですから、実際に「0で除算」した可能性もありますが、それ以外の
エラーを調べてみるべきだと思われます。

投稿時間:2005/08/02(Tue) 16:54
投稿者名:エデン
URL :
タイトル:
Re^2: 分母が固定値なのに「0で除算」!?
> VB6を長く使っているならばわかると思いますが、「0で除算」は
> VBステートメントによるエラートラップではひっかからない例外を
> VBランタイムが受け取ったときに生成する例外でもあります。

すみません、VB6長いことやってましたが知りませんでした。
ただ、仰ってることはわかる気がします。いわゆる Fatal Error的扱いで、「0で除算」を出すというの
も。

ただ今回のエラーが「0で除算」以外のエラーである可能性をどうやって探っていったらよいもの
か。。。むむむ。

ご指摘ありがとうございました。少し考えてみます。

投稿時間:2005/08/03(Wed) 05:57
投稿者名:Starfish
Eメール:
URL :
タイトル:
Re: 分母が固定値なのに「0で除算」!?
>  stSocketFrame.bytDigAlarm(1) = CByte((nStatusData(0) And &HFF00) / &HFF)

 stSocketFrame.bytDigAlarm(1)には、常に正しい値が入っているんでしょうか?
以下の1行を追加して、確認してみてはどうでしょうか?

    Debug.Print stSocketFrame.bytDigAlarm(1),nStatusData(0)

投稿時間:2005/08/03(Wed) 09:02
投稿者名:エデン
URL :
タイトル:
Re^2: 分母が固定値なのに「0で除算」!?
Startfishさん、コメントありがとうございます。

>  stSocketFrame.bytDigAlarm(1)には、常に正しい値が入っているんでしょうか?
> 以下の1行を追加して、確認してみてはどうでしょうか?
>
>     Debug.Print stSocketFrame.bytDigAlarm(1),nStatusData(0)

これは今までの調査の中で何度かやりました。通常の実行中は bytDigAlarm(1)は正しい値で表示され
ますし、VBエラー発生後、ソース画面に戻してステップ実行しても、bytDigAlarm(1)は正しい値が代入
されます。

あと最近わかったこととして、この割り算の行をコメントアウトした状態で同じことをすると、やはり
「0で除算」のVBエラーが発生し、エラー発生ポイントのソースを表示させると、この割り算ステート
メントと同じFunctionの中にある、別の行(30行程度先)の割り算ステートメントの行を指します。この
割り算も分母は固定値です。

K.J.Kさんに、「「0で除算」のVBエラーであっても実態は別のエラーで停止しているのでは?」という
コメントも頂きましたが、この状況から考えると、やはり「割り算」を切り離せないように思えてきま
した。

今のところは、自作ActiveXの処理に問題があるのでは?と考えてます。