0

C++で実装されたいくつかのネイティブメソッドをJNI経由で呼び出す単純なJavaクラスがあります。

Javaコードは次のようになります

String in_test="./xml/input/imagen_0023.xml";
//String in_test="avc";
String out_test=acr.testString2(in_test);
System.out.println("test: " + out_test);

testString2の実装は、Javaプログラムによって直接呼び出される1つのdllにあります。testString2メソッドの定義は次のとおりです。

JNIEXPORT jstring JNICALL Java_com_accsa_ocr_AutomaticCharacterRecognition_testString2(JNIEnv *env, jobject obj, jstring string) 
{
    const char *str = env->GetStringUTFChars(string, 0);

    //std::string s=amt_test_string(str);
    std::string s="hello: "+(std::string)str;
    env->ReleaseStringUTFChars(string, str);
    return env->NewStringUTF(s.c_str());
}

呼び出されたamt_test_stringは、他の場所(別のdll)で定義されています。

std::string AMT_EXPORT amt_test_string(std::string in)
{
    std::string s="path: "+in;
    std::cout<<s<<std::endl;
    return s;
}

このように実行すると、正常に動作しますが、std :: string s = amt_test_string(str)のコメントを外すとすぐに、次のようなアクセス違反エラーが発生します。

#
# A fatal error has been detected by the Java Runtime Environment:
#
#  EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x77ae2cc7, pid=8072, tid=7328
#
# JRE version: 7.0_09-b05
# Java VM: Java HotSpot(TM) Client VM (23.5-b02 mixed mode, sharing windows-x86 )
# Problematic frame:
# C  [ntdll.dll+0x52cc7]  RtlFreeHeap+0xcd

しかし、動作はどういうわけか不安定です。入力引数の長さを短くすると、つまり

//String in_test="avc"; 

プログラムは再び動作します。私がグーグルで学んだことから、それはリリースされた後のスタック割り当て変数の使用に関連するものですが、これをデバッグする方法は本当にわかりません。

編集1:VisualStudio2010とOracleのJDK1.7.09を使用してWindows732ビットでこれをコンパイルしています

編集2:AMT_EXPORTマクロは、シンボルをエクスポートするための便利なショートカットにすぎません。以下の定義を参照してください。

#ifdef WIN32
    #ifdef AMT_EXPORTS
        #define AMT_EXPORT __declspec(dllexport)
    #else
        #define AMT_EXPORT __declspec(dllimport)
    #endif
#else
    #define AMT_EXPORT
#endif
4

2 に答える 2

1

const char *私はあなたがにキャストするべきではないと思いますstd::string

std::string s="hello: "+(std::string)str;

対応するstd::stringコンストラクターを呼び出してこれを置き換えます。

于 2012-10-29T19:11:36.500 に答える
0

JNIコードのデバッグには、この記事に掲載されているメソッドが役立つ場合があります(NetbeansとVisual Studioを使用したJNIのデバッグに関するものです)。簡単です。Javaプログラムを起動し、VisualStudioで[デバッグ]->[プロセスにアタッチ]を選択し、プログラムを実行しているjava.exeプロセスを選択します。

C ++コードにブレークポイントを追加すると、VisualStudioはブレークポイントを壊します。出来上がり:)

于 2013-04-05T13:54:25.713 に答える