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