title: SIGSEGV on free()
body: <p>I am porting a C program.</p>
  
  <p>The problem I've met is SIGSEGV on free(). I can't see what's the root cause of it. it seems like heap-memory has corrupted by something.
  it doesn't occur sometimes, but very often.</p>
  
  <p>malloc didn't return NULL. so memories maybe allocated correctly.</p>
  
  <p>I am testing it on NexusOne 2.2.1
  I am using Android NDK r5b and Android SDK and Eclipse ADT and Cygwin.
  I am using android.content.res.AssetFileDescriptor to read assets in C modules.</p>
  
  <p>Here is the messages in ndk-gdb when the problem appears.</p>
  
  <pre><code>(gdb) c
  Continuing.
  
  Breakpoint 2, Java_kr_co_pkbio_Unse_DangSaJuShinSal (env=0xaa50,
      obj=0x4495b970)
      at C:/DEWR/Product/Software-Engineering/Eclipse-Workspace/Unse/jni/unse.c:1
  83
  1083                    free(strBuf);
  (gdb) next
  
  Program received signal SIGSEGV, Segmentation fault.
  0xafd11c80 in __libc_android_abort ()
     from C:/DEWR/Product/Software-Engineering/Eclipse-Workspace/Unse/obj/local/a
  meabi/libc.so
  (gdb) bt
  #0  0xafd11c80 in __libc_android_abort ()
     from C:/DEWR/Product/Software-Engineering/Eclipse-Workspace/Unse/obj/local/a
  meabi/libc.so
  #1  0xbec233bc in ?? ()
  Cannot access memory at address 0xc
  (gdb) quit
  </code></pre>
  
  <p>Here is the Java source code...</p>
  
  <pre><code>public static HashMap&lt;String, FileInfoForNativeCode&gt; fifnMap = new HashMap&lt;String, FileInfoForNativeCode&gt;();
  public static FileInfoForNativeCode openAssets(String fname) {
      FileInfoForNativeCode fifn;
  
      if (Constants.VERBOSE_LOGS)
          Log.d("TAGG", "TAGG openAssets("+fname+")");
  
      fifn = fifnMap.get(fname);
      if (fifn != null)
          return fifn;
  
      AssetFileDescriptor myDescriptor = null;
      try {
          myDescriptor = assetManager.openFd(fname+".jet");
      } catch (IOException e) {
          e.printStackTrace();
          return null;
      }
      FileDescriptor fd = myDescriptor.getFileDescriptor();
      long off = myDescriptor.getStartOffset();
      long len = myDescriptor.getLength();
  
      if (Constants.VERBOSE_LOGS)
          Log.d("TAGG", "TAGG fd:"+fd+" off:"+off+" len:"+len);
  
      fifn = new FileInfoForNativeCode(off, len, fd, myDescriptor);
      fifnMap.put(fname, fifn);
      return fifn;
  }
  </code></pre>
  
  <p>Here is the C source code...</p>
  
  <pre><code>char* getTextByIndex (TextFileBufType *filebuf, char *index) {
      #define _INDEX_PREFIX_    '@'
      int        i, j, lenBuf;
      char    *result;
      char    indexPrefix = _INDEX_PREFIX_;
      int        lenIndexPrefix = utf8len( &amp;indexPrefix );
      int        lenIndex = strlen(index);
  
      for ( i = 0 ; i &lt; filebuf-&gt;total ; i++ ) {
          //__android_log_print(ANDROID_LOG_DEBUG,"TAG", "JNI : %d -&gt; %s", i, filebuf-&gt;text[i]);
  
          if ( memcmp (filebuf-&gt;text[i], &amp;indexPrefix, lenIndexPrefix) != 0 )
              continue;
  
          if ( memcmp (filebuf-&gt;text[i]+lenIndexPrefix, index, lenIndex) != 0 )
              continue;
  
          lenBuf = 0;
          lenBuf += strlen(filebuf-&gt;text[i]);
          lenBuf++;
          for ( j = i+1 ; j &lt; filebuf-&gt;total ; j++ ) {
              if ( memcmp (filebuf-&gt;text[j], &amp;indexPrefix, lenIndexPrefix) == 0 )
                  break;
  
              lenBuf += strlen(filebuf-&gt;text[j]);
              lenBuf++;
          }
  
          result = malloc(lenBuf);
          result[0] = 0;
          strcat(result, filebuf-&gt;text[i]);
          strcat(result, "\n");
          for ( j = i+1 ; j &lt; filebuf-&gt;total ; j++ ) {
              if ( memcmp (filebuf-&gt;text[j], &amp;indexPrefix, lenIndexPrefix) == 0 )
                  break;
  
              strcat(result, filebuf-&gt;text[j]);
              strcat(result, "\n");
          }
  
          //__android_log_print(ANDROID_LOG_DEBUG,"TAG", "JNI : %d!!! -&gt; %s", i, filebuf-&gt;text[i]);
          return result;
      }
  
      return NULL;
  
      #undef _INDEX_PREFIX_
  }
  
  inline void readyFileInFile (FileInFile *fif, char *path)
  {
      jstring jstrFpath;
      jobject finfo;
      jobject descriptor;
  
      jstrFpath = (*gEnv)-&gt;NewStringUTF(gEnv, path);
      finfo = (*gEnv)-&gt;CallStaticObjectMethod(gEnv, clsUtility, midOpenAssets, jstrFpath);
      fif-&gt;offset = (*gEnv)-&gt;GetLongField(gEnv, finfo, fidOffset);
      fif-&gt;length = (*gEnv)-&gt;GetLongField(gEnv, finfo, fidLength);
      descriptor = (*gEnv)-&gt;GetObjectField(gEnv, finfo, fidDescriptor);
      fif-&gt;fd = (*gEnv)-&gt;GetIntField(gEnv, descriptor, fidDescriptorFileDescriptor);
  }
  
  jobjectArray Java_kr_co_pkbio_Unse_DangSaJuShinSal (JNIEnv *env, jobject obj) {
  //    char   *fname = "DangSaJu_ShinSal";
      int     i, fileno[4], ret_code, type;
      char    temp[256];
      char   *header[4] = { "년", "월", "일", "시" };
      char    table1[12] = { 1, 0, 3, 2, 1, 0, 3, 2, 1, 0, 3, 2 };
      char    table2[4]  = {10, 7, 4, 1};
  
      char   *index[12] = {
          "겁살",   "재살",   "천살",   "지살",   "연살",   "월살",
          "망신살", "장성살", "반안살", "역마살", "육해살", "화개살"
      };
  
      int        r_option;
      int        numBytesRead;
      char    *strBuf;
      TextFileBufType    filebuf;
      jstring buf_output[4];
      jobjectArray output;
      FileInFile fif;
  
      gEnv = env;
  
      /* 년월일시에 대한 겁살을 계산한다 */
      type = table1[BaseInfo.saju.day % 12];
      fileno[0] = (table2[type] + (BaseInfo.saju.year  % 12)) % 12;
      fileno[1] = (table2[type] + (BaseInfo.saju.month % 12)) % 12;
      fileno[2] = (table2[type] + (BaseInfo.saju.day   % 12)) % 12;
      fileno[3] = (table2[type] + (BaseInfo.saju.hour  % 12)) % 12;
      /*WriteMsg (" - 기본위치 : 생일지지(%s) --&gt; type:%d --&gt; 자(%s)에 대한 살:%s\n",
          JeeJeeStr[BaseInfo.saju.day % 12], type, JeeJeeStr[0], index[table2[type]]);
      WriteMsg (" - 년살     : 생년지지(%s) --&gt; 년%s\n", JeeJeeStr[BaseInfo.saju.year % 12],
          index[fileno[0]]);
      WriteMsg (" - 월살     : 생월지지(%s) --&gt; 월%s\n", JeeJeeStr[BaseInfo.saju.month % 12],
          index[fileno[1]]);
      WriteMsg (" - 일살     : 생일지지(%s) --&gt; 일%s\n", JeeJeeStr[BaseInfo.saju.day % 12],
          index[fileno[2]]);
      WriteMsg (" - 시살     : 생시지지(%s) --&gt; 시%s\n", JeeJeeStr[BaseInfo.saju.hour % 12],
          index[fileno[3]]);*/
  
  
      readyFileInFile(&amp;fif, "data/DangSaJu5.dat");
  
      r_option = ((int)'#' &lt;&lt; 8) &amp; 0xFF00;   /* Comment char setting */
      r_option |= (RT_OPT_RMCMT | RT_OPT_RMCRLF | RT_OPT_LTRIM | RT_OPT_RTRIM | RT_OPT_SPACES);
  
      if ( ReadTextFileToBufA (&amp;filebuf, &amp;fif, r_option) &lt; 0 ) {
          __android_log_print(ANDROID_LOG_ERROR,"TAG", "JNI : 서버측에서 치명적인 오류가 발생하여 더이상 진행할 수 없습니다.");
          return NULL;
      }
  
      for ( i = 0 ; i &lt; 4 ; i++ ) {
          sprintf (temp, "%s%s", header[i], index[fileno[i]]);
          strBuf = getTextByIndex(&amp;filebuf, temp);
          //__android_log_print(ANDROID_LOG_DEBUG,"TAG", "JNI : %s -&gt; %s", temp, strBuf );
          buf_output[i] = (*gEnv)-&gt;NewStringUTF(gEnv, strBuf);
          free(strBuf); //line number : 1083 ***It doesn't cause SIGSEGV on first for-loop-round, but on third for-round.***
          //PrintTextFile3 ("../data/DangSaJu5.dat", temp, VIEW_T_R_STR,
          //    "12신살로 알아보는 인생의 길흉화복 : %s", temp);
          /*if (i &lt; 3) {
              sprintf (temp, "\n 계속해서 %s%s에 대한 풀이를 보시겠습니까? (Y/n)",
                  header[i+1], index[fileno[i+1]]);
              ret_code = GetYesNo (temp, GETYN_YES);
              if (ret_code == GETYN_NO)  return;
          }*/
      }
  
      FreeTextFileBuf (&amp;filebuf);
      //printf ("\n [Enter]키를 누르세요.");  fflush(stdout);
      //PauseUntil (300, 0);
      #if defined (_DO_NOT_COMPILE_)
      {
          int j;
          for (i=0 ; i&lt;4 ; i++) {
              for (j=0 ; j&lt;12 ; j++) {
                  sprintf (temp, "%s%s", header[i], index[j]);
                  //PrintTextFile3 ("../data/DangSaJu5.dat", temp, VIEW_T_R_STR,
                  //    "당사주 / 인생 길흉화복 datafile test : %s", temp);
              }
          }
      }
      #endif
  
      output = (*gEnv)-&gt;NewObjectArray(gEnv, 4, clsString, NULL);
      (*gEnv)-&gt;SetObjectArrayElement(gEnv, output, 0, buf_output[0]);
      (*gEnv)-&gt;SetObjectArrayElement(gEnv, output, 1, buf_output[1]);
      (*gEnv)-&gt;SetObjectArrayElement(gEnv, output, 2, buf_output[2]);
      (*gEnv)-&gt;SetObjectArrayElement(gEnv, output, 3, buf_output[3]);
  
      return output;
  }
  </code></pre>
  
  <p>I am controlling lifetime of AssetFileDescriptors. I don't use terminated FileDescriptors.
  Do I have to re-code I/O routines in Java or not to free allocated memories?
  it often causes SIGSEGV on third for-loop. but sometimes on fourth loop.</p>
  
  <pre><code>    for ( i = 0 ; i &lt; 4 ; i++ ) {
          sprintf (temp, "%s%s", header[i], index[fileno[i]]);
          strBuf = getTextByIndex(&amp;filebuf, temp); //malloc() in this function.
          if (strBuf == NULL)
              buf_output[i] = NULL;
          else
  
          {
              buf_output[i] = (*gEnv)-&gt;NewStringUTF(gEnv, strBuf);
              free(strBuf);
          }
      }
  </code></pre>