我正在研究基于Android NDK的代码,但我不知道字符串文字的寿命有多长。
我的程序是C ++游戏,它会不时与Android Java端进行交互,例如在服务器上上传数据,连接到Facebook等。

在从Java到(本地)C ++的一次失败中,我使用了不同的方法将jstring转换为const char*,我意识到有些工作却没有。而且我不明白为什么。

例如:在JNI向下调用中,其中toCall(const char*)是常规C ++函数,在其他地方定义。

JNIEXPORT void JNICALL Java_com_alpha_beta_Gamma_onDelta(JNIEnv *env, jclass, jstring jstr) {
   // #1
   const char* cVar = jnu::ToString(jstr).c_str();
   toCall(cVar);

   // #2
   std::string strVar = jnu::ToString(jstr);
   toCall(strVar.c_str())

   // #3
   toCall(jnu::ToString(jstr).c_str());

   // #4
   std::string strVara;
   jnu::SetString(jstr, strVara);
   toCall(strVara.c_str());
}


jnu函数是:

std::string jnu::ToString(JNIEnv *env, jstring jstr) {
    if (jstr) {
        const char *cstr = env->GetStringUTFChars(jstr, NULL);
        std::string str = cstr;
        env->ReleaseStringUTFChars(jstr, cstr);
        return str;
    }
    return std::string();
}

std::string& jnu::SetString(JNIEnv* env, jstring jstr, std::string& output) {
    if (jstr) {
        const char *cstr = env->GetStringUTFChars(jstr, NULL);
        output = cstr;
        env->ReleaseStringUTFChars(jstr, cstr);
    }
    return output;
}


案例#2#3#4正常工作,而#1只是将普通垃圾发送到要调用的函数。

也许是C ++ 101,但我不知道为什么我的#1机箱有问题。有人请给我任何线索吗?

谢谢!

最佳答案

char实例拥有由std::string::c_str返回的指针指向的std::string数组。这意味着,当您调用stringc_str超出范围时,指向的数据将被删除。

这是在情况#1中发生的情况。 jnu::ToString的返回值(或任何其他临时值)在表达式的末尾超出范围,因此,一旦初始化cVar,它指向的数据就被删除,并且有一个悬空的指针。任何取消引用悬空指针的尝试都将导致未定义的行为。

在#2的情况下,由string返回的jnu::ToString被复制到strVar(或者可以移动,或者可以使用返回值优化,并且实际上没有临时创建;这没关系)。 strVar.c_str()返回的指针所指向的数据将继续存在,直到strVar超出范围或需要重新分配其存储空间为止。

在#3的情况下,由string返回的临时jnu::ToString在整个表达式中将继续存在,因此通过调用toCall可以生存。

案例4与案例2类似,除了jnu::SetString如何填充strVara

10-07 22:31