[问题记录]JNI的整型数组返回出现stack corruption

[问题记录]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");
    }
     @Override
    protected void onCreate(Bundle savedInstanceState) {
        //omission...
        int[] as = read_from_device(1);  //len
        System.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 JNICALL
	Java_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");
    }
     @Override
    protected 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);
}

  至此解决了所有的问题,而且代码也更加简介规范。

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页