我正在研究一个基于 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_str
的string
超出范围时,指向的数据将被删除。
这就是案例#1中发生的情况。jnu::ToString
(或任何其他临时)的返回值在表达式末尾超出范围,因此一旦您初始化cVar
它指向的数据,就会被删除,并且您有一个悬空的指针。 任何取消引用悬空指针的尝试都将导致未定义的行为。
在 #2 的情况下,jnu::ToString
返回的string
被复制到strVar
(或者可能被移动,或者返回值优化启动并且实际上没有创建临时;这并不重要)。strVar.c_str()
返回的指针指向的数据将继续存在,直到strVar
超出范围或需要重新分配其存储。
在 #3 的情况下,jnu::ToString
返回的临时string
将通过完整表达式继续存在,因此它通过调用toCall
而幸存下来。
案例 #4 与 #2 类似,除了jnu::SetString
如何填充strVara
。