3

I am trying to write native C code in Android using NDK. I have a function segment_offline() which takes in many arguments including an integer pointer int * num_segments. I want this pointer because I want to read the value assigned to the the integer this pointer is pointing to in my C function which acts as my JNI interface. Here is the code for segment_offline():

int * segment_offline(const SEGMENT_DATATYPE *x, const int num_samples_x, const float *svara_cents, const int *svara_lengths, const int num_svaras, const int type, const int hop_size, const float tonic, int *num_segments) {

int i;

// using DTW ...
if (0 == type) {

    filtered_samples_t fns;

    // removing the negative frequencies in Hz.
    filter_negative_samples(x, num_samples_x, &fns);

    __android_log_print(ANDROID_LOG_DEBUG, "LogNDK", "After filter_negative_samples\n");

    // converting the Hz to Cents
    convert_pitch_to_cents(fns.arr_filtered, fns.len, tonic);

    __android_log_print(ANDROID_LOG_DEBUG, "LogNDK", "After convert_pitch_to_cents\n");

    //print_double_array(fns.arr_filtered, fns.len);
    segments_t seg = segment_offline_dtw(fns.arr_filtered, fns.len, svara_cents, svara_lengths, num_svaras, hop_size);

    __android_log_print(ANDROID_LOG_DEBUG, "LogNDK", "After segment_offline_dtw\n");

    int * ret_segments = (int *) malloc(sizeof(seg.num_segments));

    __android_log_print(ANDROID_LOG_DEBUG, "LogNDK", "After allocating memory to ret_segments\n");

    // setting the value of the number of segments in the pointer that would be referred.
    // ########## I get a segmentation fault here #########
    __android_log_print(ANDROID_LOG_DEBUG, "LogNDK", "The number of segments are: %d\n", seg.num_segments);
    *num_segments = seg.num_segments;

    __android_log_print(ANDROID_LOG_DEBUG, "LogNDK", "After assigning the number of segments: %d\n", *num_segments);

    for (i = 0;i < seg.num_segments * 2; i++) {
        ret_segments[i] = fns.original_indices[seg.segments_pos[i]];
        printf("%d, ", ret_segments[i]);
    }
    printf("\n");

    __android_log_print(ANDROID_LOG_DEBUG, "LogNDK", "Returning from segment_offline\n");

    return ret_segments;
}

The JNI C function that I have written is:

JNIEXPORT jintArray JNICALL Java_com_camut_audioiolib_dsp_DSPAlgorithms_segmentOffline
  (JNIEnv *env, jclass cls, jdoubleArray x, jint numSamples, jfloatArray svaraCents,
  jintArray svaraLengths, jint numSvaras, jint type, jint hopSize, jfloat tonic) {

    jdouble *xDouble = (*env)->GetDoubleArrayElements(env, x, NULL);
    jfloat *svaraCentsFloat = (*env)->GetFloatArrayElements(env, svaraCents, NULL);
    jint *svaraLengthsInt = (*env)->GetIntArrayElements(env, svaraLengths, NULL);

    __android_log_print(ANDROID_LOG_DEBUG, "LogNDK", "The size of the type tonic is: %d", sizeof(tonic));

    int num_segments;

    int * segments = (int *) segment_offline(xDouble, numSamples, svaraCentsFloat, svaraLengthsInt,
        numSvaras, type, hopSize, tonic, &num_segments);

    if (NULL == segments) {
       return NULL;
    }

    // releasing the allocated memories ...
    (*env)->ReleaseDoubleArrayElements(env, x, xDouble, JNI_ABORT);
    (*env)->ReleaseFloatArrayElements(env, svaraCents, svaraCentsFloat, JNI_ABORT);
    (*env)->ReleaseIntArrayElements(env, svaraLengths, svaraLengthsInt, JNI_ABORT);

     return NULL;

  }

You see in the above code that I have initialized the num_segments as an int variable and passing the address of this variable to the function mentioned above.

So, it seems that I am unable to derefer the int pointer. Any suggestions on this. I need this pointer because I am returning other value as my function return value.

Swapnil
  • 1,870
  • 2
  • 23
  • 48
  • What `seg.num_segments` is? Post complete `segment_offline()`. – Sergio Aug 01 '16 at 13:39
  • I tried printing its value with `%d` and it prints 1 for me which is kind of expected. – Swapnil Aug 01 '16 at 13:40
  • Anyway, could you post `segment_offline()` definition? And why are you using cast to `int *`? Function already has proper return type. – Sergio Aug 01 '16 at 13:42
  • I have posted the definition for `segment_offilne()` and marked the place where I get the segmentation fault. – Swapnil Aug 01 '16 at 13:46
  • The JNI dictates that the size of a `jint`/`jfloat`/`jdouble` is 32/32/64 bits. Are you positive that this matches the sizes of the C `int`/`float`/`double` types on whatever architecture you're running this on? – Michael Aug 01 '16 at 14:08

1 Answers1

2

Just a guess. Someone corrupts your num_segments before derefer. Try print its value immediately at function begin and then before crash line. Also crash log shows that SIGSEGV occurs on address 0x60000000, that is unlikely an address of stack object.

EDIT

Also incorrect argument value may be caused by call to incorrectly declared function, i.e. if you have call to function that is not defined yet or defined in another translation unit - you must provide forward declaration that tells to compiler about actual argument list and return type. Note that C89 allows implicit function declaration. In case if you don't declare the function - compiler supposes that it has int return type and takes any number of any arguments. See here for details. Note, that mismatch of definition and call signatures causes undefined behavior.

P.S. Also absence of forward declaration may force you to cast function return since compiler expects it to be int.

Community
  • 1
  • 1
Sergio
  • 8,099
  • 2
  • 26
  • 52
  • I don't think so because I have not used this pointer variable anywhere else other than dereferencing it. Thanks for the thought anyways. – Swapnil Aug 01 '16 at 13:58
  • Just a correction. The address is actually getting modified when I pass it to the C function beneath the JNI layer. So the value in the JNI layer : `Address in the JNI function: 0x9e192784` and the value just after entering `segment_offilne()` is `After just entering the function: 0x60000000`. I somehow feel now this is not the correct way to solve this problem. Is it? – Swapnil Aug 01 '16 at 14:08
  • Sounds like ABI problem. Is there forwarding declaration (or definition) of `segment_offline()` before JNI function? – Sergio Aug 01 '16 at 14:16
  • Wow ... That was the mistake. I had a header file but I had not included in the JNI functions file (although it was included in the file where my `segment_offilne()`function was defined. What is the reason for this? Can you point me to some resource for this?). Thanks a ton. Can you please modify the answer to say this and I will change the question as well and accept your answer. – Swapnil Aug 01 '16 at 14:34