简体   繁体   中英

Android NDK - Fatal signal 11 (SIGSEGV) on device only

I have a really strange issue going on with my app. First of all, my app is to test the NDK capacity to manipulate some raw audio data with libraries automatically generated by MatLab. The algorithm is really simple.

My C library was generated automatically from MatLab code and I made the necessary changes to make it work with C. The code is working flawlessly in the emulator, but when I run the application on my Nexus 4 device it crashes SOMETIMES, giving me a SIGSEGV fatal error.

This is my C code:

JNIEXPORT jshortArray JNICALL Java_com_test_audiocapteffect_MainActivity_addeffects
(JNIEnv* env, jobject thiz, const jshortArray input, int32_T SampleRate, int32_T sizeofx) {
__android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, "NDK: Creating/Getting Array Elements");
jshort* x = (*env)->GetShortArrayElements(env, input, 0);
//int16_T* x = (int16_T*)j_input;
jshortArray output;
output = (jshortArray)((*env)->NewShortArray(env, sizeofx));
jshort* y = (*env)->GetShortArrayElements(env, output, 0);
//int16_T* y = (int16_T*)j_output;

__android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, "NDK: Creating variables");
emxArray_real_T *temp;
uint32_T b_y;
int32_T i;
int32_T loop_ub;
int16_T iv0[sizeofx];
real_T thresh;
uint32_T delayedindex;
emxInit_real_T(&temp, 1);
b_y = (uint32_T)rt_roundd(0.3 * (real_T)SampleRate);

__android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, "NDK: Filling y with zeros");
for(i = 0; i<sizeofx; i++) {
    y[i] = 0;
}

__android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, "NDK: Adding distortion part 1");
/* add distortion */
/* distortion function */
i = temp->size[0];
temp->size[0] = sizeofx;
emxEnsureCapacity((emxArray__common *)temp, i, (int32_T)sizeof(real_T));

__android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, "NDK: Adding distortion part 2");
// get the absolute values of each element
for (i = 0; i < sizeofx; i++) {
    iv0[i] = b_abs(x[i]);
}

__android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, "NDK: Adding distortion part 3");
thresh = 1.2 * mean(iv0, sizeofx);
for (i = 1; i <= sizeofx; i = (int32_T)((uint32_T)i + 1U)) {
    if ((real_T)x[(int32_T)(uint32_T)i - 1] > thresh) {
        temp->data[(int32_T)(uint32_T)i - 1] = thresh;
    } else if ((real_T)x[i - 1] < -thresh) {
        temp->data[(int32_T)(uint32_T)i - 1] = -thresh;
    } else {
        temp->data[(int32_T)(uint32_T)i - 1] = (real_T)x[i - 1];
    }
}


__android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, "NDK: Adding delay part 1");
/* add delay */
/* delay function */
/* modified by Thomas Horta */    
for (i = 1; i <= sizeofx; i = (int32_T)((uint32_T)i + 1U)) {
    delayedindex = (uint32_T)i - b_y;
    if (1U < delayedindex) {
    } else {
        delayedindex = 1U;
    }
    if (i==1) {
        __android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, "NDK: Adding delay part 2");
    }
    if ((uint32_T)i - b_y < 1U) {
        y[(int32_T)(uint32_T)i - 1] = (int16_T)(temp->data[(int32_T)(uint32_T)i - 1]);
    } else {
        y[(int32_T)(uint32_T)i - 1] = (int16_T)(temp->data[(int32_T)(uint32_T)i - 1] +
        0.3 * temp->data[(int32_T)delayedindex - 1]);
    }
}

__android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, "NDK: Freeing resources");
emxFree_real_T(&temp);

(*env)->ReleaseShortArrayElements(env, input, x, 0);
(*env)->ReleaseShortArrayElements(env, output, y, 0);

__android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, "NDK: Returning output");
return output;  }

My error occurs when the function gets to the part where I have a log output with the message "NDK: Adding delay part 2" , the loop that fills the output array.

EDIT: This is the emxArray structure: (it was automatically generated by Matlab too)

typedef struct emxArray_real_T
{
    real_T *data;
    int32_T *size;
    int32_T allocatedSize;
    int32_T numDimensions;
    boolean_T canFreeData;
} emxArray_real_T;

The variable types have those strange names because of MatLab conventions but they are just typedefs for the variable types. Even though they are just typedefs, I think the error might be caused because of a conversion of real type to a int16_T ( double to short in Java equivalents)

My LogCat displays this:

06-06 15:36:12.382: I/AudioCaptEffect(2503): Add effects to the audio
06-06 15:36:12.382: D/NDK_SimpleCApp(2503): NDK: Creating/Getting Array Elements
06-06 15:36:12.382: D/NDK_SimpleCApp(2503): NDK: Creating variables
06-06 15:36:12.382: D/NDK_SimpleCApp(2503): NDK: Filling y with zeros
06-06 15:36:12.382: D/NDK_SimpleCApp(2503): NDK: Adding distortion part 1
06-06 15:36:12.382: D/NDK_SimpleCApp(2503): NDK: Adding distortion part 2
06-06 15:36:12.382: D/NDK_SimpleCApp(2503): NDK: Adding distortion part 3
06-06 15:36:12.392: D/NDK_SimpleCApp(2503): NDK: Adding delay part 1
06-06 15:36:12.392: D/NDK_SimpleCApp(2503): NDK: Adding delay part 2
06-06 15:36:12.392: A/libc(2503): Fatal signal 11 (SIGSEGV) at 0x72905a08 (code=1), thread 2769 (Thread-15238)

Does anyone have any idea of why is this happening? The strangest things are that this is happening only on the Nexus 4 (only android device I have to test) and most of the times I run the app (not all the times).

I fixed the problem but didn't quite understand why it was happening exactly since sometimes it would work and sometimes it wouldn't (completely random).

As you can see I made use of some unsigned int variables because MatLab created the code this way, making everything more difficult and prone to errors when used with Java because Java doesn't have unsigned variables.

So basically what I did was tell MatLab coder that all my variables are signed and generated the code again, then I just replaced some parts of the old code (in the question) with parts of the new code generated (without any uint_16_T variables).

Now the app is working perfectly both on the emulator and on the device. I tested with a lot of different inputs with different sizes and sample rates and the app never crashed again.

For those who are interested, the new code is:

JNIEXPORT jshortArray JNICALL Java_com_test_audiocapteffect_MainActivity_addeffects
(JNIEnv* env, jobject thiz, const jshortArray input, int32_T SampleRate, int32_T sizeofx) {

__android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, "NDK: Creating/Getting Array Elements");
jshort* x = (*env)->GetShortArrayElements(env, input, 0);
//int16_T* x = (int16_T*)j_input;
jshortArray output;
output = (jshortArray)((*env)->NewShortArray(env, sizeofx));
jshort* y = (*env)->GetShortArrayElements(env, output, 0);
//int16_T* y = (int16_T*)j_output;

__android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, "NDK: Creating variables");
emxArray_real_T *temp;
int32_T b_y;
int32_T i;
int16_T iv0[sizeofx];
real_T thresh;
uint32_T delayedindex;
emxInit_real_T(&temp, 1);
b_y = (int32_T)rt_roundd(0.3 * (real_T)SampleRate) - 1;

__android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, "NDK: Filling y with zeros");
for(i = 0; i<sizeofx; i++) {
    y[i] = 0;
}

__android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, "NDK: Adding distortion part 1");
/* add distortion */
/* distortion function */
i = temp->size[0];
temp->size[0] = sizeofx;
emxEnsureCapacity((emxArray__common *)temp, i, (int32_T)sizeof(real_T));

__android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, "NDK: Adding distortion part 2");
// get the absolute values of each element
for (i = 0; i < sizeofx; i++) {
    iv0[i] = b_abs(x[i]);
}

__android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, "NDK: Adding distortion part 3");
thresh = 1.2 * mean(iv0, sizeofx);
for (i = 0; i + 1 <= sizeofx; i++) {
    if ((real_T) x[i] > thresh) {
        temp->data[i] = thresh;
    } else if ((real_T) x[i] < -thresh) {
        temp->data[i] = -thresh;
    } else {
        temp->data[i] = (real_T) x[i];
    }
}


__android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, "NDK: Adding delay part 1");
/* add delay */
/* delay function */
/* modified by Thomas Horta */    
for (i = 0; i <= sizeofx - 1; i++) {
    delayedindex = i - b_y;
    if (1 < delayedindex) {
    } else {
        delayedindex = 1;
    }

    if (i==1) {
        __android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, "NDK: Adding delay part 2");
    }

    if (i - b_y < 1) {
        y[i] = temp->data[i];
    } else {
        y[i] = temp->data[i] + 0.35 * temp->data[delayedindex - 1];
    }
}

__android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, "NDK: Freeing resources");

emxFree_real_T(&temp);
(*env)->ReleaseShortArrayElements(env, input, x, 0);
(*env)->ReleaseShortArrayElements(env, output, y, 0);

__android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, "NDK: Returning output");
return output;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM