- PR -

自作拡張ストアドの実行で不明な現象か・・・Help!

1
投稿者投稿内容
かね
会議室デビュー日: 2004/10/22
投稿数: 4
投稿日時: 2004-10-22 11:23
Windows2000 MS SQL7.0 SP2 開発環境はVC++6.0で拡張ストアドプロシージャーを作成しました。
作成したDLL内部には 関数A(仮名称) と 関数B(仮名称) が混在しております。
この両関数ともに、デバッグでビルトしデバッグ実行(トレース実行)を行うと問題無く動作するのですが、リリースにすると、 関数A は正常動作 関数B では下記のエラーが出て動作しません。
-------------------------------------------------------------------------------
[Microsoft][ODBC SQL Server Driver][Shared Memory]ConnectionCheckForData (CheckforData()).
[Microsoft][ODBC SQL Server Driver][Shared Memory]一般的なネットワーク エラーです。ネットワークのマニュアルを調べてください。

接続が解除されました
-------------------------------------------------------------------------------

この両関数ともに、関数内部より、外の C.exe(仮名称)をCreateProcessで起動し、戻り値に
従い処理を行う物ですが、両関数共に、殆ど同じ処理をしており、関数からのリターン値である文字列
だけが違うような内容なのです。
尚、C.exeの内容は、内部で設定ファイルに従い、ADOで指定のサーバーのDBを参照するEXEとなっております。
これは、MFCを用いた拡張ストアド内よりDBの指定テーブルの参照方法が判らなかった為、逃げてとしてこのような
構成にしてしまいました。

当DLLの呼び出しはクエリーアナライザーで下記の構文で呼び出しております。
関数Aの場合
 declare @a varchar(100)
 declare @b varchar(100)
 declare @c varchar(100)
 select @a=''
 select @b='埼玉県さいたま市'
 exec @a=master..xp_A @b, @c OUTPUT
 print '戻りa='+@a
 print '戻りb='+@b
 print '戻りc='+@c
↑は正常動作

関数Bの場合
 declare @a varchar(100)
 declare @b varchar(100)
 declare @c varchar(100)
 select @a=''
 select @b='_B9FCDBCDAA194959'
 exec @a=master..xp_B @b, @c OUTPUT
 print '戻りa='+@a
 print '戻りb='+@b
 print '戻りc='+@c

↑は呼び出し時に下記となる
 [Microsoft][ODBC SQL Server Driver][Shared Memory]ConnectionCheckForData (CheckforData()).
 [Microsoft][ODBC SQL Server Driver][Shared Memory]一般的なネットワーク エラーです。ネットワークのマニュアルを調べてください。
 接続が解除されました

何か渡す文字列がマズイのでしょうか?
関数Bを実行した場合、実際には関数Bに入る前でSQL自体がエラーを返している様に見受けられます。
また、関数Bに関数Aに渡す様な全角文字列を入れると実行されます。
微細な情報で構いませんので、何かお教しえ下さい。
散々調べたのですが、何故、同様の処理を行っているのに、関数Bだけがエラーとなるのかどなたかお知恵をお貸し頂ければと思い、投稿しました。宜しくお願い致します。
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2004-10-22 11:42
unibon です。こんにちわ。

引用:

かねさんの書き込み (2004-10-22 11:23) より:
Windows2000 MS SQL7.0 SP2 開発環境はVC++6.0で拡張ストアドプロシージャーを作成しました。
作成したDLL内部には 関数A(仮名称) と 関数B(仮名称) が混在しております。
この両関数ともに、デバッグでビルトしデバッグ実行(トレース実行)を行うと問題無く動作するのですが、リリースにすると、 関数A は正常動作 関数B では下記のエラーが出て動作しません。


拡張ストアドプロシージャーは作った経験はないのですが、デバッグビルドで動いてリリースビルドで動かない場合(やその逆の場合)は、初期化されていない変数を使ったり、正しくないポインタを使ってメモリや、特にスタックを壊したり、といったプログラムの間違いがあることが多いです。このあたりのチェックはどこまで済まされているかが気になります。
かね
会議室デビュー日: 2004/10/22
投稿数: 4
投稿日時: 2004-10-22 11:53
ご返答ありがとうございます。
無論ポインタ関連や初期化を含めメモリーリークも一応全てチェック済みです。またこの内部で使用している部分は別件のWindowsアプリケーションでも使っており、コードのバグは枯れていると思われます。(内部処理自体は大した物ではありませんし)
不思議なのは、リリースでも渡す文字列を全角に変更しただけで、DLL内部の関数まで入って来てちゃんと終了すると言う事です。感触としては、問題の'_B9FCDBCDAA194959'を渡した際にはSQLの段階でエラーを返してそうですが、何か文字列の渡し方に問題があるのか?と疑っています。関数Aでは全角も'_B9FCDBCDAA194959' もOKなのも不思議だが・・・。
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2004-10-23 21:13
unibon です。こんにちわ。

エラーメッセージをもとに探して、
http://www.examnotes.net/archive79-2002-10-75304.html
などを参考にしたのですが、エラーログにもう少し詳細な情報が書かれている可能性がありますが、このエラーログはどうなっているでしょうか。

なお、ちょっと良く分からないのですが、拡張ストアドプロシージャーから、別プロセスを生成して、自分自身の SQL Server に接続している、ということでしょうか。
エラーは、その別プロセス内の ADO の実行結果として受け取っているのでしょうか、それとも、拡張プロシージャーを呼んだ側が受け取っているのでしょうか?
ビルドの違いは、拡張ストアドプロシージャーのビルドの違いということでしょうか。「C.exe(仮名称)」のビルドの違いではないということでしょうか。

#以下、後で追加。

上記の「エラーログ」とは、
http://www.microsoft.com/japan/msdn/library/ja/trblsql/tr_hightrbl_3fw3.asp
のようなもののことを指します。

あと、思うのは、
引用:

かねさんの書き込み (2004-10-22 11:23) より:
尚、C.exeの内容は、内部で設定ファイルに従い、ADOで指定のサーバーのDBを参照するEXEとなっております。
これは、MFCを用いた拡張ストアド内よりDBの指定テーブルの参照方法が判らなかった為、逃げてとしてこのような
構成にしてしまいました。


を解決したほうが良いのかもしれませんが、拡張ストアドプロシージャーに引数で渡すだけではだめなのでしょうか(でもやはり簡単ではないのでしょうね)。

[ メッセージ編集済み 編集者: unibon 編集日時 2004-10-23 21:21 ]
かね
会議室デビュー日: 2004/10/22
投稿数: 4
投稿日時: 2004-10-23 21:34
unibonさん、親身な対応ありがとうございます。拡張ストアド自体の作成は初めてでしたので、不明な事ばかりでしたが、やっと原因が判明し解決しました。当初、外部EXEからADOでDBにアクセスしたりと、変な構成になっているのがユーザー数を増やしたりして影響しているのか?とか、渡す文字列が悪く、DLL呼び出し前にSQLでエラーを返している・・・と思い込んでおりましたが、実際は、全然違う内容でした。この主要処理部分は通常のDLLをVCやVBのアプリケーションから呼び出し何の問題も無く使用出来ておりましたので、問題無い物と思っておりましたが、超初心者的なミスでsscanfを内部で使用しておりましたが、2バイトの半角文字(16進数表記)をchar 1バイトの変数で受けており、問題無いとおもっていたら、拡張ストアドので上記を実行すると、この部分でどうやらぶっ壊してしまっていたらしく、一度intの変数に取った後、キャストしてcharに入れる事で正常に動作する様になりました。
メッセージで出ていたネットワークエラーは全く的外れなメッセージで、惑わされてしまっておりました。SQLで拡張ストアドを実行する際はSQLのメモリー空間で実行する為か、かなりシビアな事になるのですね・・・。非常に下らない内容で時間を掛けてしまいましたが、勉強になりました。
最後まで、色々とお教え頂き、unibonさんには非常に感謝しております。
(unibonさんのメモリーを壊してる・・・が大ヒントでした!)
また何かの際には宜しくお願い致します。
かね
会議室デビュー日: 2004/10/22
投稿数: 4
投稿日時: 2004-10-23 22:11
書き忘れましたが、c.exeでは別プロセスで別途ADOを用いDBのテーブルにアクセスし、その情報をシェアードメモリーで拡張ストアドのDLLに返しております。DLLではその得た情報を元に処理を行っております。
これは元々VBやVC++のアプリケーションで呼び出すDLLを作ったのですが、当初DLL内部でADOの呼び出そうとしたのですが、DLLの場合、ADOの処理を書き込むと、コンパイル時に2重定義等が発生し、コンパイルでエラーが出て駄目でした。そこで変則的ですが、外部EXEに切り出し、必要に応じて起動する様にしました。(ダサイですが・・・)
その流れで拡張ストアドの方も同じ構成でちょっとしたI/O部分の焼き直しだけで作ったのです。
拡張ストアドのサンプルや参考文献はまともな物が少なく、悪戦苦闘しておりました。
拡張ストアドからでもODBCやDBLIBを用いテーブルにアクセス出来るようですが(VC++のサンプル)、MFCを用いたDLLのプロジェクト内部からDBLIBを呼び出そうとしたのですが、これまたコンパイルのオプションのせいか?それとも他の理由からか、かなり色々試したのですが、実装出来ませんでした・・・。(この時点で八方塞がり状態で泣きが入っておりました)

と言う訳で、実際にはその外部EXEからのアクセスが問題の原因ではなかったのですが、超初歩的なミスで現在ホッとした反面、自己嫌悪に陥っております。
本当に貴重なご意見に感謝しております。
1

スキルアップ/キャリアアップ(JOB@IT)