[问题记录]JNI的整型数组返回出现stack corruption
??在项目中编写了一个返回整型数组的JNI代码,但是在测试时发现问题,会产生stack corruption错误,debug之后发现是return的地方出错,故在此记录。本人水平有限,如果理解有错,请多多指教。
1.错误代码
C:
//native-lib.c
JNIEXPORT jintArray JNICALL
Java_com_example_final2_MainActivity_read_1from_1device(JNIEnv *env, jobject thiz, jint len) {// TODO: implement read_from_device()int n=0,i=0;char buf[100];int *buf_int;buf_int = (int*)malloc(sizeof(int)*len);int l = len;//从设备节点fd_io中读取一个字符串if (read(fd_io,buf,l)){jintArray jntarray = (*env)->NewIntArray(env, len);jint * jintp = (*env)->GetIntArrayElements(env, jntarray, NULL);//将char类型数组转为int类型数组,并将int类型数组赋值给jntarray类型数组for(i=0;buf[i]!='\0';i++){buf_int[n++] = buf[i]-'0';jintp[i] = buf_int[i];}free(buf_int);(*env)->ReleaseIntArrayElements(env, jntarray, jintp, 0);return jntarray;}else{return 0;}
??这个函数的功能是将从节点中read出的含有一个元素的char数组转为int类型数组再转为jntarray类型数组输出。
JAVA:
public class MainActivity extends AppCompatActivity {// Used to load the 'native-lib' library on application startup.static {System.loadLibrary("native-lib");}@Overrideprotected void onCreate(Bundle savedInstanceState) {//omission...int[] as = read_from_device(1); //lenSystem.out.println(Arrays.toString(as));//omission...}public native int[] read_from_device(int len);
}
??但是在执行是出现了堆栈破损错误,同时另一个read很多元素的char数组执行同样的操作并return却不会报错。
??原因在没有理解:
(*env)->ReleaseIntArrayElements(env, jntarray, jintp, 0);
??这一步操作的意义是,将jintp的值传给jntarray,同时将jintp指针释放,然而,jintp是定义jntarray空间的指针,因此,当只有一个数据将要被传递时,jintp释放时,jntarray所在空间也被销毁。
总而言之,在有(*env)->ReleaseIntArrayElements(env, jntarray, jintp, 0)语句时,不应该return jntarray,会造成错误。
2.修改代码
??因此,上述功能的代码可以修改为:
C:
JNIEXPORT jint JNICALLJava_com_example_final2_MainActivity_final_1read_1return(JNIEnv *env, jobject thiz,jintArray get_int_array) {//新代码直接将char->int变换后的值赋给JAVA传来的整型数组指针,从而直接改变JAVA中对应的整形数组的值,省去了中间传递的部分。char buf_read[2];if (read(fd_io,buf_read,1)) {jint *jintp = (*env)->GetIntArrayElements(env, get_int_array, NULL);for (int i = 0; buf_read[i] != '\0'; i++) {jintp[i] = buf_read[i] - '0';}//将创建的jintp指针用完后及时释放,ReleaseIntArrayElements的作用就是将数据处理结构同步到 java 数组,并释放数组指针(*env)->ReleaseIntArrayElements(env, get_int_array, jintp, 0);return 1;}else return 0;}
JAVA:
public class MainActivity extends AppCompatActivity {// Used to load the 'native-lib' library on application startup.static {System.loadLibrary("native-lib");}@Overrideprotected void onCreate(Bundle savedInstanceState) {//omission...int[] test_return_array={0}; //这里一定要给整型数组赋初值,否则无法传回值test_return(test_return_array);//打印日志的方式输出结果Log.d("return array",Arrays.toString(test_return_array));for(int i :test_return_array){System.out.println(i);}//omission...}public native int final_read_return(int[] get_int_array);
}
??至此解决了所有的问题,而且代码也更加简介规范。