Joseph
Joseph

Reputation: 76

How to debug a Fatal Signal 6 crash on Android Studio for Native C Code?

I am working to find a crash that happens in Native C in our Android Studio.

We know where that the error originates from a library in Native C. Most probably from a Garbage handler.   We have tried to Release the variables in different ways with no success yet. The strange part the code works fine for Android 5.0 and up. 

I also googled for how to debug NDK in Android studio by adding

Enable app debugging in your AndroidManifest.xml file by including an <application> element that sets the android:debuggable attribute to true.

and adding a log:

__android_log_print(ANDROID_LOG_VERBOSE, APPNAME, "The value R %f G %f B %f , H %f S %f V %f   ", rgbData[0], rgbData[1], rgbData[2], rgbData[3], rgbData[4], rgbData[5]);

However, the monitor still doesn't print anything. Below the piece of code and the crash log.

Any help would be highly appreciated.

#include <jni.h>

//#include <android/log.h>

#define APPNAME "handroid"

#define MAX(a,b) \
   ({ __typeof__ (a) _a = (a); \
       __typeof__ (b) _b = (b); \
     _a > _b ? _a : _b; })

#define MIN(a,b) \
    ({ __typeof__ (a) _a = (a); \
        __typeof__ (b) _b = (b); \
      _a < _b ? _a : _b; })


double* rgbData;
int rgbDataSize = 0;

JNIEXPORT
void
JNICALL
Java_handroid_classes_Camera_YUVtoRBGHSV(JNIEnv * env, jobject obj, jdoubleArray rgb_hsv, jbyteArray yuv420sp, jint width, jint height)
{
    int             sz;
    int             i;
    int             j;
    int             Y;
    int             Cr = 0;
    int             Cb = 0;
    int             pixPtr = 0;
    int             jDiv2 = 0;
    int             R = 0;
    int             G = 0;
    int             B = 0;
    double          tR = 0;
    double          tG = 0;
    double          tB = 0;
    int             cOff;
    int             w = width;
    int             h = height;
    sz = w * h;

    int pixel;
    int uvp;
    int y1192;
    int y;
    int v;
    int u;
    int yp;

    //for hsv
    double min, max, delta, hsv_h, hsv_s, hsv_v;

    jboolean isCopy;
    jbyte* yuv = (*env)->GetByteArrayElements(env, yuv420sp, &isCopy);

    if(rgbDataSize < sz) {
        double tmp[6];
        rgbData = &tmp[0];
        rgbDataSize = sz;
    }

    //Calculate pixel colors
    for (j = 0, yp = 0; j < h; j++) {
                uvp = sz + (j >> 1) * w, u = 0, v = 0;
                for (i = 0; i < w; i++, yp++) {

                            y = (0xff & yuv[yp]) - 16;
                            if (y < 0) y = 0;
                            if ((i & 1) == 0) {
                                v = (0xff & yuv[uvp++]) - 128;
                                u = (0xff & yuv[uvp++]) - 128;
                            }
                            y1192 = 1192 * y;
                            R = (y1192 + 1634 * v);
                            G = (y1192 - 833 * v - 400 * u);
                            B = (y1192 + 2066 * u);

                            if (R < 0) R = 0;
                            else if (R > 262143) R = 262143;
                            if (G < 0) G = 0;
                            else if (G > 262143) G = 262143;
                            if (B < 0) B = 0;
                            else if (B > 262143) B = 262143;


                            pixel = 0xff000000 | ((R << 6) & 0xff0000) | ((G >> 2) & 0xff00) | ((B >> 10) & 0xff);

                            tR += (pixel >> 16) & 0xff;
                            tG += (pixel >> 8) & 0xff;
                            tB += (pixel >> 0) & 0xff;

                }
            }


    //Create RGB sum (average pixel)
    rgbData[0] = (double)(tR/255/sz);
    rgbData[1] = (double)(tG/255/sz);
    rgbData[2] = (double)(tB/255/sz);

    //Calculate HSV
    min = MIN(rgbData[0], MIN(rgbData[1], rgbData[2]));
    max = MAX(rgbData[0], MAX(rgbData[1], rgbData[2]));
    hsv_v = max;
    delta = max - min;

    if( max != 0 ){
        hsv_s = delta / max;

        if( rgbData[0] == max )
            hsv_h = ( rgbData[1] - rgbData[2] ) / delta;
        else if( rgbData[1] == max )
            hsv_h=2+(rgbData[2]-rgbData[0])/delta;
        else
            hsv_h=4+(rgbData[0]-rgbData[1])/delta;
            hsv_h *= 60;

        if( hsv_h < 0 )
            hsv_h += 360;


        rgbData[3] = hsv_h;
        rgbData[4] = hsv_s;
        rgbData[5] = hsv_v;

    }else {
        // r = g = b = 0
        hsv_s = 0;
        hsv_h = -1;
        rgbData[3] = hsv_h;
        rgbData[4] = hsv_s;
        rgbData[5] = hsv_v;

    }

    //Log the data in Android
    //__android_log_print(ANDROID_LOG_VERBOSE, APPNAME, "The value R %f G %f B %f , H %f S %f V %f   ", rgbData[0], rgbData[1], rgbData[2], rgbData[3], rgbData[4], rgbData[5]);

    //Set RGB
    (*env)->SetDoubleArrayRegion(env, rgb_hsv, 0, 1, ( jdouble * ) &rgbData[0] );
    (*env)->SetDoubleArrayRegion(env, rgb_hsv, 1, 1, ( jdouble * ) &rgbData[1] );
    (*env)->SetDoubleArrayRegion(env, rgb_hsv, 2, 1, ( jdouble * ) &rgbData[2] );

    //Set HSV
    (*env)->SetDoubleArrayRegion(env, rgb_hsv, 3, 1, ( jdouble * ) &rgbData[3] );
    (*env)->SetDoubleArrayRegion(env, rgb_hsv, 4, 1, ( jdouble * ) &rgbData[4] );
    (*env)->SetDoubleArrayRegion(env, rgb_hsv, 5, 1, ( jdouble * ) &rgbData[5] );


    //Release the array data
    //(*env)->ReleaseByteArrayElements(env, yuv420sp, yuv, JNI_ABORT);
    (*env)->ReleaseByteArrayElements(env, yuv420sp, yuv, 0);
    //(*env)->ReleaseDoubleArrayElements(env, yuv420sp, yuv,rgbData,min,max,0);

}

Crash log

04-03 15:30:27.687 5547-5547/com.hlib E/dalvikvm: VM aborting
 04-03 15:30:27.687 5547-5547/com.hlib A/libc: Fatal signal 6 (SIGABRT) at 0x000015ab (code=-6), thread 5547 (it.hlib)

Upvotes: 1

Views: 636

Answers (1)

Ghazi.Bousselmi
Ghazi.Bousselmi

Reputation: 11

I am not familiar with Native C under android, but I will try :)

  • The macros MIN & MAX look very peculiar, not sure about the syntax "({ instr })", would it be valuated to the last instruction ? why not use a more conventional definition "MAX(a, b) ((a) > (b) ? (a) : (b))" ? It would incur 3 evaluations instead of 2 ; but in any case, the MIN & MAX are used in the code in a nested manner, in this case it might be more efficient to use plain functions.

  • rgbData is initialized with a stack variable tmp[6] that will be destroyed after the end of the if block,

    if(rgbDataSize < sz) {
        double tmp[6];
        rgbData = &tmp[0];
        rgbDataSize = sz;
    }
    
  • the result of

    jbyte* yuv = (*env)->GetByteArrayElements(env, yuv420sp, &isCopy);
    

    should be checked wether it is null, does it return an array of at least (w*h + w * (h/2) + w) bytes ? accessed through:

    v = (0xff & yuv[uvp++]) - 128; 
    u = (0xff & yuv[uvp++]) - 128;
    
  • Are the "width" and "height" parameters correct with regards to the size of the bitmap "yuv" ?

  • the block

    if( max != 0 ){
    

    will divide by "delta", which might be 0.

  • does the next block need "{ }" to include both instructions ?

    else
        hsv_h=4+(rgbData[0]-rgbData[1])/delta;
        hsv_h *= 60;
    
  • it seems that the 6 function calls could be replaced with only 1 call

    <= (*env)->SetDoubleArrayRegion(env, rgb_hsv, 0, 1, ( jdouble * ) &rgbData[0] );
    => (*env)->SetDoubleArrayRegion(env, rgb_hsv, 0, 6, ( jdouble * ) &rgbData[0] );
    

That's what I could find out with a brief look.

Upvotes: 1

Related Questions