お世話になっております。
以前も何度か似たような質問をさせて頂いたのですが
未だ解決に至りませんので、再度質問させていただきます。
現在、JavaからC++の自作dllを呼び出し、
C++dllから外部開発dllの関数を使いハードウェアへコマンドを送信する。
というプログラムを開発しております。
そこで、プログラムを動かし、終了させると
hs_pid...log が生成されます。
ログの内容(一部)↓
#
# A fatal error has been detected by the Java Runtime Environment:
#
# EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x1a212cd2, pid=4716, tid=4332
#
# JRE version: 7.0_05-b05
# Java VM: Java HotSpot(TM) Client VM (23.1-b03 mixed mode windows-x86 )
# Problematic frame:
# C [PCardRW32.dll+0x22cd2] crwSetLineControl+0x203b2
#
# Failed to write core dump. Minidumps are not enabled by default on client versions of Windows
#
# An error report file with more information is saved as:
# C:\eclipse\workspace\ReWriteCard\hs_err_pid4716.log
#
# If you would like to submit a bug report, please visit:
# http://bugreport.sun.com/bugreport/crash.jsp
#
どうやら、メモリアクセス違反を起こしているみたいなのですが
logの内容は理解できません。
そこで、私が開発しましたプログラムを見て頂き、
BSTRの使い方がおかしいとのご指摘を受け、
しばらく調べていたのですが、どうにも改善できません。
C++のプログラム↓
JNI002_API jstring JNICALL Java_rewritecard_JNI001_DT(JNIEnv *env, jobject obj, jint jport) {
int port = (int)jport;
long int ret = 0;
test = crwOpenPort(port, 9600 , "8" , "N");
BSTR s1 = ::SysAllocString(L"s1");
BSTR s2 = ::SysAllocString(L"s2");
BSTR s3 = ::SysAllocString(L"s3");
ret = crwSendCommandRR(port,1,1000,1000,0,"DT",":1",2,&s1,&s2,&s3);
char* src = (char*)s3;
jstring jstr = env->NewStringUTF(src);
::SysFreeString(s1);
::SysFreeString(s2);
::SysFreeString(s3);
return jstr;
}
上記のプログラムのBSTRの使い方が悪いのは、承知致しておりますが
WideCharToMultiByte関数を使い、jstrへ変換し、
いかなる方法を試してもJava上で文字化けしますので
とりあえず今は現状で使用しております。
そこで試しに、以下のようなプログラムにしてみました
これだと、logファイルは生成されません。
JNI002_API jstring JNICALL Java_rewritecard_JNI001_DT(JNIEnv *env, jobject obj, jint jport) {
int port = (int)jport;
long int ret = 0;
/*
test = crwOpenPort(port, 9600 , "8" , "N");
BSTR s1 = ::SysAllocString(L"s1");
BSTR s2 = ::SysAllocString(L"s2");
BSTR s3 = ::SysAllocString(L"s3");
ret = crwSendCommandRR(port,1,1000,1000,0,"DT",":1",2,&s1,&s2,&s3);
char* src = (char*)s3;
jstring jstr = env->NewStringUTF(src);
::SysFreeString(s1);
::SysFreeString(s2);
::SysFreeString(s3);
*/
jstring jstr = env->NewStringUTF("");
return jstr;
}
しかし、以下のようにすると
logファイルが生成されます。
JNI002_API jstring JNICALL Java_rewritecard_JNI001_DT(JNIEnv *env, jobject obj, jint jport) {
int port = (int)jport;
long int ret = 0;
test = crwOpenPort(port, 9600 , "8" , "N");
/*
BSTR s1 = ::SysAllocString(L"s1");
BSTR s2 = ::SysAllocString(L"s2");
BSTR s3 = ::SysAllocString(L"s3");
ret = crwSendCommandRR(port,1,1000,1000,0,"DT",":1",2,&s1,&s2,&s3);
char* src = (char*)s3;
jstring jstr = env->NewStringUTF(src);
::SysFreeString(s1);
::SysFreeString(s2);
::SysFreeString(s3);
*/
jstring jstr = env->NewStringUTF("");
return jstr;
}
だとすると、logとBSTRの問題は別物だと判断してもいいんでしょうか
また、Java → 自作dll → 他社dll という構図に問題があるんでしょうか
ささいなことでも構いません
ご教授宜しくお願い致します。
No.4ベストアンサー
- 回答日時:
>さきほどのログは、C++のプログラムをビルドした時のログです。
>私が作成しました、JNI001のプログラムは、DT以外にもメソッド、と言っていいんでしょうか
>メソッドがありますので、DT以外の警告だと思います。
それならそれでJava_rewritecard_JNI001_DT以外の関数のコンパイルログを省略する方が・・・
Java_rewritecard_JNI001_DTのコンパイル時の警告を確認したかったのに今まで話にも出てこなかった他の部分のコンパイルログを抜粋されても判断に困るわけですが。
>extern DllImport short int WINAPI crwOpenPort(short int, LONG, LPCSTR, LPCSTR);
>extern DllImport short int WINAPI crwSendCommandRR(short int,
>short int,
>LONG,
>LONG,
>short int,
>LPCTSTR,
>LPCTSTR,
>short int,
>BSTR*,
>BSTR*,
>BSTR* );
これ書き間違えとかはないですか?
crwOpenPortでは引数にLPCSTRが使われていて、crwSendCommandRRでは引数にLPCTSTRが使われているというのは統一性に欠けるというか・・・
とりあえずこれがあってるのであれば少なくともcrwOpenPortの使い方は間違ってないと思いますので、それでjavaがログを出力するということは私が思いつくところでは
・javaがスレッドに割り当てているスタック領域をcrwOpenPortが食いつぶしている
・実はcrwOpenPortは再入不可で、再入された
くらいです。
>それとひとつ気になったんですが
>C++のプロジェクトのプロパティで、文字セットの設定を
>設定なしにしてるんですが、こちらは関係ないでしょうか。
crwSendCommandRRの引数にLPCTSTRがあるので関係すると思いますがプロトタイプ宣言からの推測でしかないので他社性DLLの提供元に確認してみてください。
考えが及んでおりませんでした。
せっかくのご助言、無駄にするような行い
大変申し訳ありません。
関数の書き間違えについては、間違いではないようです。
確認致しましたが、記載どおりでした。
では、
・javaがスレッドに割り当てているスタック領域をcrwOpenPortが食いつぶしている
・実はcrwOpenPortは再入不可で、再入された
こちらの2つの状況を調べてみます。
困り果てておりましたので大変助かりました。
ありがとうございました。
No.3
- 回答日時:
>正常終了となっていますし、
>引数として渡されるintは、shortを超える数字ではないので、
>良いかなと思い無視しておりましたが、これらの警告は無視できないものなんでしょうか
「引数として渡されるintは、shortを超える数字ではないので、」
こういった理由がある分には無視するのはかまわないです。
無視していないかどうか尋ねたのは、無視してはいけない警告を無視してないかどうかなので。
ところでこのコンパイルのログは何をコンパイルしたものなんでしょうか?
質問文に書かれているJava_rewritecard_JNI001_DT()のコンパイルログにしては
>jstring jstr = env->NewStringUTF(src);
関数内でenvは使われているのに
>1>JNI002.cpp(16): warning C4100: 'env' : 引数は関数の本体部で 1 度も参照されません。
という警告が出てるのが不思議なんですけど。
もし可能であれば
crwOpenPort(), crwSendCommandRR()
のプロトタイプ宣言教えていただけませんか?
この回答への補足
ご回答ありがとうございます。
さきほどのログは、C++のプログラムをビルドした時のログです。
私が作成しました、JNI001のプログラムは、DT以外にもメソッド、と言っていいんでしょうか
メソッドがありますので、DT以外の警告だと思います。
プロトタイプ宣言、意味をはき違えてましたら申し訳ないですが
こちらでよろしいでしょうか。
extern DllImport short int WINAPI crwOpenPort(short int, LONG, LPCSTR, LPCSTR);
extern DllImport short int WINAPI crwSendCommandRR(short int,
short int,
LONG,
LONG,
short int,
LPCTSTR,
LPCTSTR,
short int,
BSTR*,
BSTR*,
BSTR* );
それとひとつ気になったんですが
C++のプロジェクトのプロパティで、文字セットの設定を
設定なしにしてるんですが、こちらは関係ないでしょうか。
お手数おかけしますが、宜しくお願いいたします。
No.2
- 回答日時:
>関数の使い方
>ということに関して、dllを開発した会社へプログラムを見て頂き、
>問い合わせを行ったところ
>BSTRの使い方がおかしいとの指摘を頂きました。
確かにBSTRの使い方におかしいところはあると思うんですが(私はBSTRは使ったことないのでMSDNにあるドキュメントを読んだだけですが)
http://msdn.microsoft.com/ja-jp/library/xda6xzx7 …
ただ、いくらBSTRの使い方がおかしいにしてもワイド文字列が設定されるところにマルチバイト文字列が設定されて返ってきてる事もおかしいんです。
他にも気になってる事があって
>ret = crwSendCommandRR(port,1,1000,1000,0,"DT",":1",2,&s1,&s2,&s3);
第9~11引数にはBSTRのポインタを要求していながら第6, 第7引数がマルチバイト文字列というのも不思議な気がしてます。
もしかして他社製DLLを使用するためのヘッダファイルをインクルードしていなかったり、コンパイル時の警告を無視していたりしませんか?
この回答への補足
ご回答ありがとうございます。
さきほど、C++のプログラムを確認いたしました。
インクルードはできております。
インクルードしていなかったら、関数を指定するときに、エラーが出ますので
できていると思うんですが、
コンパイル時の警告に関しては
さきほど、C++の警告レベルがレベル3だったのを、レベル4に変えて
コンパイルしなおしてみました。
以下が実行結果の出力です。
1>------ ビルド開始: プロジェクト: JNI002, 構成: Release Win32 ------
1> stdafx.cpp
1> dllmain.cpp
1>dllmain.cpp(7): warning C4100: 'lpReserved' : 引数は関数の本体部で 1 度も参照されません。
1>dllmain.cpp(4): warning C4100: 'hModule' : 引数は関数の本体部で 1 度も参照されません。
1> JNI002.cpp
1>JNI002.cpp(16): warning C4100: 'obj' : 引数は関数の本体部で 1 度も参照されません。
1>JNI002.cpp(16): warning C4100: 'env' : 引数は関数の本体部で 1 度も参照されません。
1>JNI002.cpp(53): warning C4244: '引数' : 'int' から 'short' への変換です。データが失われる可能性があります。
・ 文字数制限のため割愛致します
・ 場所が違うのみで、エラー内容は同じです(割愛分56行)
・
1>JNI002.cpp(425): warning C4100: 'obj' : 引数は関数の本体部で 1 度も参照されません。
1>JNI002.cpp(425): warning C4100: 'env' : 引数は関数の本体部で 1 度も参照されません。
1> ライブラリ C:\username\username\Documents\Visual Studio 2010\Projects\JNI002\Release\JNI002.lib とオブジェクト C:\username\username\Documents\Visual Studio 2010\Projects\JNI002\Release\JNI002.exp を作成中
1> コード生成しています。
1> コード生成が終了しました。
1> JNI002.vcxproj -> C:\username\username\Documents\Visual Studio 2010\Projects\JNI002\Release\JNI002.dll
========== ビルド: 1 正常終了、0 失敗、0 更新不要、0 スキップ ==========
そして、これが完了した後
プログラム C:\パス・・・\JNI002.dllを開始できません
というポップアップが出てOKボタンをクリックします。
正常終了となっていますし、
引数として渡されるintは、shortを超える数字ではないので、
良いかなと思い無視しておりましたが、これらの警告は無視できないものなんでしょうか
No.1
- 回答日時:
>そこで、私が開発しましたプログラムを見て頂き、
>BSTRの使い方がおかしいとのご指摘を受け、
>しばらく調べていたのですが、どうにも改善できません。
何か勘違いされてるようなんですが私は「BSTRの使い方がおかしい」とはいってませんよ?
「他社製DLLの使い方を間違ってないか確認した方がよいと思いますよ」と書いてたはずですが。
少なくともcrwSendCommandRR()の第9~11引数はBSTRへのポインタを要求するにしてはマルチバイト文字列へのアドレスが格納されて返ってくる事がおかしいんです(BSTRが扱うのはワイド文字列)
で、crwSendCommandRR()をはじめとする他社製DLLが提供している関数の使い方が正しいのか間違ってるのかは、その仕様を知らない私らには判断できません。
なのでその他社製DLLの提供元に関数の使い方を確認することをお勧めします(以前からいってる)。
この回答への補足
説明不足でありました。
お気を悪くされたようですね。
大変申し訳ないです。
wormholeさんから指摘して頂いた
関数の使い方
ということに関して、dllを開発した会社へプログラムを見て頂き、
問い合わせを行ったところ
BSTRの使い方がおかしいとの指摘を頂きました。
そのほかにも、教えてGooにて、wormholeさんではない方から、
BSTRの使い方がおかしいと指摘をいただきました。
説明不足、大変申し訳ありません
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# C言語で再起関数とポインタを用いて文字列反転をする方法がわかりません。 4 2023/04/29 20:32
- C言語・C++・C# c言語でユーザ関数を利用して入力された文字列を反転させるプログラムを作りたいです。 3 2023/01/29 19:47
- Visual Basic(VBA) エクセルVBAで教えて頂きたいのですが? 2 2022/12/31 20:28
- 英語 節を列挙する例示表現について 2 2022/08/15 13:52
- Java Java です 途中は省いてますが for(int i = 0; i < 25; i ++) { s 4 2022/05/20 23:36
- Java java 入力 3 4 3 出力 ABC DEFG HIJ このようなプログラムの書き方を教えてくだ 2 2022/07/15 14:18
- 数学 写真について質問なのですが、 ①の図の面積Sを求めるとき、②と③の図の面積、つまりS=S2+S3で求 4 2023/04/27 17:20
- Android(アンドロイド) スマホについて詳しい方に質問です。京セラのandroid oneシリーズでアンドロイドOS 10まで 1 2023/05/04 23:10
- 工学 電気回路の2端子対回路 (1)スイッチS1のみが開いているときの電流I1を求めよ。 (2)スイッチS 4 2023/05/29 16:40
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
C言語をコンパイルするとコンピ...
-
<unistd.h>をVisualStudioでつ...
-
実行後にコンパイルに失敗しま...
-
アプリケーションのDLLファイル...
-
math.hに含まれる関数が使えない
-
ビープ音が鳴りません・・・
-
c言語です コンパイルした時に...
-
再起動しないとADOが使えなくな...
-
VS2010環境で2点ほど質問
-
<math.h>ヘッダを入力している...
-
'hcw'がみつかりません
-
すべてのリビルド: 0 正常、 0 ...
-
VCでコンパイラ実行時に警告を...
-
</body>の直上にJavaScriptを入...
-
C言語で作ったらWindowsでもMac...
-
C言語で、配列を使ったsinカー...
-
Linux(g++)とAIX(XL C++)の挙動...
-
64bit環境で32bitでコンパイル...
-
VC++6.0の混在モード
-
CLRアプリと通常のアプリとの違い
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
<unistd.h>をVisualStudioでつ...
-
アプリケーションのDLLファイル...
-
共有ライブラリの内容確認について
-
シリアル通信の受信待ちについて
-
C#で char型とstring型の比較で...
-
64ビットのlinuxで32ビットメモ...
-
Verilog_HDLでのdefineとifdef
-
math.hに含まれる関数が使えない
-
自作DLLの中身を暗号化
-
C言語で作ったらWindowsでもMac...
-
実行後にコンパイルに失敗しま...
-
lhafileをインストールしたい
-
c言語です コンパイルした時に...
-
ビープ音が鳴りません・・・
-
すべてのリビルド: 0 正常、 0 ...
-
gcc バージョン違いによるコン...
-
Cのコンパイルでコメントアウト...
-
CLRアプリと通常のアプリとの違い
-
「インクルードファイル 'pthre...
-
MVSマシンで0C7でABENDしたので...
おすすめ情報