JNI 中常量字符* 的寿命是多少?

What is the lifespan of a const char* in JNI?

本文关键字:多少 常量 字符 JNI      更新时间:2023-10-16

我正在研究一个基于 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只是将普通垃圾发送到函数进行调用。

也许是 101 C++,但我不明白为什么我的 #1 案例有问题。有人请给我任何线索吗?

谢谢!

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

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

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

在 #3 的情况下,jnu::ToString返回的临时string将通过完整表达式继续存在,因此它通过调用toCall而幸存下来。

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