エラー40040が出たのですが理解できません

解決


sk  2005-09-01 11:59:23  No: 91919  IP: [192.*.*.*]

ボードを追加してVB5でプログラムしました。
2回ぐらい止まったらしいので、エラーを調べようとしたのですが、VBのコールバック関数のせいか、表示が出る前に消えてしまいます。
どうにか1度ビデオにとることが出来たのですが、Error40040  が出ておりました。
ヘルプにも載っていたのですが、いまいち理解できません。

ヘルプの内容
無効な種類のバリアント型 (Variant) が検出されました。数値として文字列のデータ型 (リモート データ) を渡そうとした場合など、正しい型に変更できない値をリモート データ オブジェクト (RDO) のメソッドまたはプロパティに渡そうとすると、このエラーが発生します。
このエラーを回避するには、渡される値が操作に対して適切なデータ型であることを確認してください。列の値の場合、列の Type プロパティを調べることによって、正しいデータ型を渡しているかどうかを確認できます。

なんとなく分かることは、違う型のデータを無理やり代入したために起きたエラー  と言う事なのですが、リモートデータ、リモートデータオブジェクトが何なのかすら分からず、どうしたものかと思っています。
そこで、どうすればこのエラーが出るのかを具体的な例で教えていただけたらと思います。
具体的なエラーの出方が分かれば対策の仕方も分かるかもしれないので。
よろしくお願いします。

編集 削除
名無し  2005-09-01 12:13:50  No: 91920  IP: [192.*.*.*]

>ボードを追加して
いきなり意味不明

編集 削除
sk  2005-09-01 13:57:15  No: 91921  IP: [192.*.*.*]

すいません。
ボートはインターフェースのカウンタボードです。エンコーダのカウントをさせてます。
一定カウントごとに割込みをしています。
プログラムのどこが悪いかの検討すら付かないので、どこが悪いかの検討をつけるためにエラーの出し方が分かれば悪そうなところも見つかるかな?と思いました。

編集 削除
medaka  2005-09-01 15:39:48  No: 91922  IP: [192.*.*.*]

>渡される値が操作に対して適切なデータ型であることを確認してください
これ調べればいいのでは?

編集 削除
sk  2005-09-01 18:28:21  No: 91923  IP: [192.*.*.*]

データ型が違う時の組み合わせはやって見たのですが、違うエラーが出てしまうので、ソース全部眺めても多分見つからないかな?と思いまして、ソースは調べてないです。
ちなみに、組み合わせたのは long integer double variant string  です。

編集 削除
ガッ  2005-09-01 18:37:20  No: 91924  IP: [192.*.*.*]

"カウンタボード"を使ったことがないのでなんともいえないけど…
とりあえず、"無理やり代入"する直前に、代入するものの型を調べてみて、
それが無理やり代入される方が予想しているかどうかを次に調べる。
これで解決しそうだけど…

編集 削除
sk  2005-09-01 19:22:22  No: 91925  IP: [192.*.*.*]

無理やり代入しないようにプログラムは作ってあるはずなんで、その無理やりの場所の検討がつかなくて^^;
実は元が自分で作ったプログラムじゃあ無いので、ソース見るのも結構大変なんですが。
一番の問題はめったに止まらないのでプログラムを走らせてデバックしたところで、直ったのか、ただ単にまだ出ないだけなのかが分からなくて困っています。
ネットで調べてもめったに出ないエラーなのか、なかなかヒットしません。

編集 削除
ねろ  2005-09-02 10:04:52  No: 91926  IP: [192.*.*.*]

ちょっと確認なんですが、カウンターからのデーターのは
コールバックの関数内で処理されるのでしょうか、あるいは
ハード付属の専用のOCSXなんかの割り込み処理ルーチンで
処理されるんでしょうか?

編集 削除
さるべーじ  2005-09-02 10:16:19  No: 91927  IP: [192.*.*.*]

まず、513以上のエラー番号は、ユーザー定義です。
RDOを組み込んでいる場合には、RDOが独自に40040を使っているかもしれませんが、
今回のエラーがRDO関係であるとは限りません。

というか、今までの説明でDB回りの話が一切出てきていないので、
RDO回りのエラーである可能性は低いのではないか、
拡張ボード用のドライバ(もしくは相当のミドルウェア?)が
独自に出しているエラーの可能性が高いのではないか、と推測します。
また、意外とボードとまったく関係ない別の要件の可能性もあります。

私でしたら、

(1) そのプログラムの中で拡張エラーを定義している部分はないか?

    (「40040」で全モジュール検索かけるとヒットするはず。
     複数のプロジェクトに分かれている場合はそのすべてに対して
     検索をかける必要があります。)

(2) ボードドライバ(?)の中で40040エラーを独自に定義していないか?

    まずはマニュアル。VB用のOCXやDLLが提供されているのであれば、
    起こりうるエラーについても一覧表等が記載されているのが普通です。
    なければ、メーカーに問い合わせてみる必要があります。

(3) (1)・(2)で原因を絞り込めなければ、トレースログを仕込みます。

    「止まる」ということですので、当該プロジェクトのすべての
    プロシージャ(SubとFunction)の冒頭に、そのプロシージャが動作したことがわかる
    ログをテキストファイルに吐き出すような記述を追加して、
    しばらく運用してもらいます。
    止まった時にログを見れば、どのプロシージャでハングアップしたかがわかります。
    日時も同時に吐くようにしておけば、プロシージャのコンボ状態もわかります。
    ハングするプロシージャ(とそれを呼び出す親プロシージャ群)がわかれば、
    今度はその中で使用しているアヤシそうな変数等の中身をログに吐き出す記述を
    追加し、さらに運用してもらいます。
    これで止まれば、おおまかなハング時の状況が把握できるのではないでしょうか。
    もちろん一回で済まない場合もありますので、疑う変数その他を増減させながら
    何階かのトライは必要かもしれません。

けっこう面倒な作業かもしれませんが、このくらいはやらないと
今回のトラブルの原因を特定するのは難しいと思います。

編集 削除
sk  2005-09-02 11:42:15  No: 91928  IP: [192.*.*.*]

ねろさんへ
カウンターの処理はコールバック関数内で処理してます。
他にはRS-232Cの通信もさせています。

さるべーじさんへ
ユーザー定義なんですか。道理で検索しても見つかりにくいと思いました。
(1)はまったく予想していませんでした。検索してみます。
(2)ですが、ボードとのやり取りは関数を使っています。(dll)なので、エラーは関数の戻り値になりますので、エラーの表示をする場合にはメッセージbox等で表示してやらないとだめなので、ちょっと微妙です。でも、一応ボードのエラーの一覧表を見てみます。
(3)はいい技ですね。止まっても、exeにした後でもデバックできる。この技は今回だけでなく今後も使わせていただきたいと思います。

編集 削除
ガッ  2005-09-02 11:52:30  No: 91929  IP: [192.*.*.*]

※実はさっきからDLLにしたら、
  参照しているプロジェクトを開いているIDEごと落ちるプログラムのデバッグをしています(orz

コールバック関数はちゃんと後処理をしなくてはいけなかったり(アタリマエじゃ…)、
IDEでのデバッグにも神経を使うなど色々大変です。
また、内部状態の出力にメッセージボックスやDebug出力を使うと、
それによってさらなる誤作動が発生したりするかもしれません。
なので、いきなり最終手段の(3)をオススメします。

デバッガ使うのも面倒だしなぁ…どうすっかなー……はぁ(orz

編集 削除
ねろ  2005-09-02 11:58:43  No: 91930  IP: [192.*.*.*]

発環境でのデバッグが可能ですか?
コールバック関数内でのエラーの為、開発環境でのデバッグでも、
エラーでプログラムが停止すること無しに、ハング又は
スレッドが落ちてしまうとでしょうか?

編集 削除
sk  2005-09-02 15:52:11  No: 91931  IP: [192.*.*.*]

コールバック関数内でのえらーというよりも、えらーが出てプログラムが進まないはずなのにコールバック関数に飛ぶため、強制終了している感じだと思います。
開発環境でのデバックは出来なくはないのですが、処理に時間がかかるせいか、時々何の前触れもなく落ちます。(割り込み処理が終わらないうちにカウンタがいっぱいになって2重に割り込みがかかるから?と思っています。)

編集 削除
通ってみた  2005-09-02 16:39:39  No: 91932  IP: [192.*.*.*]

>>割り込み処理が終わらないうちにカウンタがいっぱいになって2重に割り込みがかかるから?

処理の最初に「今処理中なのかどうかをチェックする」って基本だと思うけど・・・

編集 削除
ねろ  2005-09-02 17:09:37  No: 91933  IP: [192.*.*.*]

カウンターではないのですが、かなり高速なデーターをコールバックで処理した
ことがあります。
コールバックで厄介なことは、コールバック内でブレークポイントがかけられない
事と、エラーが起きるとIDEごと落ちるか、スレッドがハングしてしまいます。
その時のプログラムは相手の機械との関係上、コンピューターの再起動をすると
初期化に5分以上かかるもので、その為フリーズする毎に5分待ち、デバッグの時間
よりも待ち時間の方が長くなりました。
そこでコールバック内の処理をなるべく短くすることを考えました。
具体的には、コールバック内では送られて来るデーターを配列に入れるだけ、
処理はメインプログラムでLoopを回して、配列のデーターを監視して、データーが新しく
配列に入れられると、その処理を行うというものでした。
こうすることにより、殆どの処理をコールバックルーチンの外側に移すことが出来、
IDE環境でのデバッグ可能となりました。
まあ、他人の作ったソフトの手直しなら、結構難しいでしょうがこんな考え方も
有るということで。

編集 削除
ガッ  2005-09-02 17:29:33  No: 91934  IP: [192.*.*.*]

どうも、先ほど ※ で愚痴ったことが解決したので
一応フィードバックしておきます。

・コールバック関数の内部では、IDEによるエラー補足をしないこと。
  →IDEが割り込みをして、一時的に内部メモリをロックしているかもしれません。
    コールバック関数は外側から無条件に呼ばれるかもしれませんので、
    絶対にIDEが割り込みするようにしてはいけません
  →どうしてもしたい場合は、
    On-Errorステートメントで、エラーを自分で補足し、
    そのあとに、コールバック関数を安全に解除し、
    エラーを表示する。
    という方法があります。一応大丈夫みたいです。

私のバグは、DLLが参照しているDLL内部でCopyMemoryを使っていたのですが、
そこでオフセットの基数を 0 とするところを 1 としていたために起こったようです。
解決するまでIDEを三つ起動させ、ゴリゴリやっては三つ落とす…ということを延々として、何とか原因をみつけられました。

でゎ、頑張ってください(orz

編集 削除
sk  2005-09-09 21:10:14  No: 91935  IP: [192.*.*.*]

その後エラーが出なくてデバックが進まない状況だったんですが、怪しい部分を直してとりあえず終了する事になってしまいました。

又出た時にやる事になると思うのですが、とりあえずここで解決のチェックを入れます。

皆さんありがとうございました。

編集 削除