我试图在一个单独的线程中从Java调用以下函数:
extern "C" JNIEXPORT jdoubleArray
JNICALL
Java_de_bastian_sip2labor_MainActivity_filtertest(JNIEnv *env, jobject, jdoubleArray ka)
{
double b_y1[121];
int k;
int j;
static const double dv0[12] = { 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.65 };
jdouble *sig1;
sig1=env->GetDoubleArrayElements(ka, 0);
memset(&b_y1[0], 0, 121U * sizeof(double));
for (k = 0; k < 12; k++) {
for (j = k; j + 1 < 122; j++) {
b_y1[j] += dv0[k] * sig1[j - k];
}
}
env->ReleaseDoubleArrayElements(ka,sig1,JNI_ABORT);
jdoubleArray output = env->NewDoubleArray( sizeof(b_y1) );
env->SetDoubleArrayRegion( output, 0, sizeof(b_y1), &b_y1[0] );
return output;
}
它是一个过滤器,它接受一个双精度数组,修改它,并将其作为函数结果返回给java。
应用程序在启动时崩溃,我假设因为这一行:
env->SetDoubleArrayRegion( output, 0, sizeof(b_y1), &b_y1[0] );
第一次遇到这个问题时,在调用onPause()之后发生了这个问题,而带调用的单独线程可能仍在运行。因此我认为它与生命周期有关。是否有可能在尝试执行SetDoubleArrayRegion()之前以某种方式检查活动是否仍处于活动状态,还是可能是另一个问题?
奇怪的是,代码工作正常,直到最近: 我开始读取一个文件,然后将其用作过滤器的输入。在全新安装后第一次启动应用程序时,它会要求用户授予文件读取权限。如果用户授予他们应用程序正常工作,你可以看到过滤器输出。从那时起,当应用程序启动时,已经授予了读取文件的权限,应用程序尝试立即启动过滤器,然后崩溃。
简单的logcat输出:
A/libc: Fatal signal 11 (SIGSEGV), code 2, fault addr 0x89fa2830 in tid 8498 (Thread-5)
详细的Logcat输出:
#00 pc 0001a21e /system/lib/libc.so (memcpy+46)
#01 pc 004394a6 /system/lib/libart.so (_ZN3art3JNI23SetPrimitiveArrayRegionIP13_jdoubleArraydNS_6mirror14PrimitiveArrayIdEEEEvP7_JNIEnvT_iiPKT0_+1174)
#02 pc 0041e87c /system/lib/libart.so (_ZN3art3JNI20SetDoubleArrayRegionEP7_JNIEnvP13_jdoubleArrayiiPKd+44)
#03 pc 0015c9d2 /system/lib/libart.so (_ZN3art8CheckJNI23SetPrimitiveArrayRegionEPKcNS_9Primitive4TypeEP7_JNIEnvP7_jarrayiiPKv+1474)
#04 pc 00144665 /system/lib/libart.so (_ZN3art8CheckJNI20SetDoubleArrayRegionEP7_JNIEnvP13_jdoubleArrayiiPKd+53)
#05 pc 00000e10 /data/app/de.bastian.sip2labor-FUb-fvR-Nwyxco0g-cmxow==/lib/x86/libsip2labor-lib.so (_ZN7_JNIEnv20SetDoubleArrayRegionEP13_jdoubleArrayiiPKd+160)
#06 pc 00000fcc /data/app/de.bastian.sip2labor-FUb-fvR-Nwyxco0g-cmxow==/lib/x86/libsip2labor-lib.so (Java_de_bastian_sip2labor_MainActivity_filtertest+428)
#07 pc 0063ec67 /system/lib/libart.so (art_quick_generic_jni_trampoline+71)
#08 pc 000049d3 /dev/ashmem/dalvik-jit-code-cache (deleted)
我在这里做错了什么?提前感谢您的努力。
答案 0 :(得分:1)
在拨打b_y1
时,您正在阅读env->SetDoubleArrayRegion( output, 0, sizeof(b_y1), &b_y1[0] );
数组的末尾
sizeof(b_y1)
以字节为单位返回数组的大小,不是元素的数量。在我的平台上,这是968,但是你的b_y1
只有121个元素,所以这是未定义的行为。
您可以通过传递121
(数组的实际大小)而不是sizeof(b_y1)
来解决此问题。但是既然你正在使用C ++,我建议切换到使用std::array
,因为它保持了你的大小,并且通常有一个更高级别的api:
std::array<double, 121> b_y1;
int k;
int j;
static const double dv0[12] = { 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.65 };
jdouble *sig1;
sig1 = env->GetDoubleArrayElements(ka, 0);
b_y1.fill(0);
for (k = 0; k < 12; k++) {
for (j = k; j + 1 < 122; j++) {
b_y1[j] += dv0[k] * sig1[j - k];
}
}
env->ReleaseDoubleArrayElements(ka, sig1, JNI_ABORT);
jdoubleArray output = env->NewDoubleArray(b_y1.size());
env->SetDoubleArrayRegion(output, 0, b_y1.size(), b_y1.data());
return output;