首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >free()上的SIGSEGV

free()上的SIGSEGV
EN

Stack Overflow用户
提问于 2011-02-28 11:46:35
回答 2查看 1.8K关注 0票数 0

我正在移植一个C程序。

我遇到的问题是free()上的SIGSEGV。我不明白它的根本原因是什么。看起来堆内存被什么东西损坏了。这种情况有时不会发生,但很常见。

malloc未返回NULL。所以内存分配可能是正确的。

我正在NexusOne 2.2.1上测试它,我使用的是Android NDK、r5b和Android SDK,以及Eclipse ADT和Cygwin。我正在使用android.content.res.AssetFileDescriptor读取C模块中的资源。

以下是问题出现时ndk-gdb中的消息。

代码语言:javascript
复制
(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

这是Java源代码...

代码语言:javascript
复制
public static HashMap<String, FileInfoForNativeCode> fifnMap = new HashMap<String, FileInfoForNativeCode>();
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;
}

这是C源代码..。

代码语言:javascript
复制
char* getTextByIndex (TextFileBufType *filebuf, char *index) {
    #define _INDEX_PREFIX_    '@'
    int        i, j, lenBuf;
    char    *result;
    char    indexPrefix = _INDEX_PREFIX_;
    int        lenIndexPrefix = utf8len( &indexPrefix );
    int        lenIndex = strlen(index);

    for ( i = 0 ; i < filebuf->total ; i++ ) {
        //__android_log_print(ANDROID_LOG_DEBUG,"TAG", "JNI : %d -> %s", i, filebuf->text[i]);

        if ( memcmp (filebuf->text[i], &indexPrefix, lenIndexPrefix) != 0 )
            continue;

        if ( memcmp (filebuf->text[i]+lenIndexPrefix, index, lenIndex) != 0 )
            continue;

        lenBuf = 0;
        lenBuf += strlen(filebuf->text[i]);
        lenBuf++;
        for ( j = i+1 ; j < filebuf->total ; j++ ) {
            if ( memcmp (filebuf->text[j], &indexPrefix, lenIndexPrefix) == 0 )
                break;

            lenBuf += strlen(filebuf->text[j]);
            lenBuf++;
        }

        result = malloc(lenBuf);
        result[0] = 0;
        strcat(result, filebuf->text[i]);
        strcat(result, "\n");
        for ( j = i+1 ; j < filebuf->total ; j++ ) {
            if ( memcmp (filebuf->text[j], &indexPrefix, lenIndexPrefix) == 0 )
                break;

            strcat(result, filebuf->text[j]);
            strcat(result, "\n");
        }

        //__android_log_print(ANDROID_LOG_DEBUG,"TAG", "JNI : %d!!! -> %s", i, filebuf->text[i]);
        return result;
    }

    return NULL;

    #undef _INDEX_PREFIX_
}

inline void readyFileInFile (FileInFile *fif, char *path)
{
    jstring jstrFpath;
    jobject finfo;
    jobject descriptor;

    jstrFpath = (*gEnv)->NewStringUTF(gEnv, path);
    finfo = (*gEnv)->CallStaticObjectMethod(gEnv, clsUtility, midOpenAssets, jstrFpath);
    fif->offset = (*gEnv)->GetLongField(gEnv, finfo, fidOffset);
    fif->length = (*gEnv)->GetLongField(gEnv, finfo, fidLength);
    descriptor = (*gEnv)->GetObjectField(gEnv, finfo, fidDescriptor);
    fif->fd = (*gEnv)->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) --> type:%d --> 자(%s)에 대한 살:%s\n",
        JeeJeeStr[BaseInfo.saju.day % 12], type, JeeJeeStr[0], index[table2[type]]);
    WriteMsg (" - 년살     : 생년지지(%s) --> 년%s\n", JeeJeeStr[BaseInfo.saju.year % 12],
        index[fileno[0]]);
    WriteMsg (" - 월살     : 생월지지(%s) --> 월%s\n", JeeJeeStr[BaseInfo.saju.month % 12],
        index[fileno[1]]);
    WriteMsg (" - 일살     : 생일지지(%s) --> 일%s\n", JeeJeeStr[BaseInfo.saju.day % 12],
        index[fileno[2]]);
    WriteMsg (" - 시살     : 생시지지(%s) --> 시%s\n", JeeJeeStr[BaseInfo.saju.hour % 12],
        index[fileno[3]]);*/


    readyFileInFile(&fif, "data/DangSaJu5.dat");

    r_option = ((int)'#' << 8) & 0xFF00;   /* Comment char setting */
    r_option |= (RT_OPT_RMCMT | RT_OPT_RMCRLF | RT_OPT_LTRIM | RT_OPT_RTRIM | RT_OPT_SPACES);

    if ( ReadTextFileToBufA (&filebuf, &fif, r_option) < 0 ) {
        __android_log_print(ANDROID_LOG_ERROR,"TAG", "JNI : 서버측에서 치명적인 오류가 발생하여 더이상 진행할 수 없습니다.");
        return NULL;
    }

    for ( i = 0 ; i < 4 ; i++ ) {
        sprintf (temp, "%s%s", header[i], index[fileno[i]]);
        strBuf = getTextByIndex(&filebuf, temp);
        //__android_log_print(ANDROID_LOG_DEBUG,"TAG", "JNI : %s -> %s", temp, strBuf );
        buf_output[i] = (*gEnv)->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 < 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 (&filebuf);
    //printf ("\n [Enter]키를 누르세요.");  fflush(stdout);
    //PauseUntil (300, 0);
    #if defined (_DO_NOT_COMPILE_)
    {
        int j;
        for (i=0 ; i<4 ; i++) {
            for (j=0 ; j<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)->NewObjectArray(gEnv, 4, clsString, NULL);
    (*gEnv)->SetObjectArrayElement(gEnv, output, 0, buf_output[0]);
    (*gEnv)->SetObjectArrayElement(gEnv, output, 1, buf_output[1]);
    (*gEnv)->SetObjectArrayElement(gEnv, output, 2, buf_output[2]);
    (*gEnv)->SetObjectArrayElement(gEnv, output, 3, buf_output[3]);

    return output;
}

我在控制AssetFileDescriptors的生命周期。我不使用终止的FileDescriptors。我是否必须在Java中对I/O例程进行重新编码,或者不需要释放分配的内存?它经常导致第三个for循环上的SIGSEGV。但有时在第四个循环中。

代码语言:javascript
复制
    for ( i = 0 ; i < 4 ; i++ ) {
        sprintf (temp, "%s%s", header[i], index[fileno[i]]);
        strBuf = getTextByIndex(&filebuf, temp); //malloc() in this function.
        if (strBuf == NULL)
            buf_output[i] = NULL;
        else

        {
            buf_output[i] = (*gEnv)->NewStringUTF(gEnv, strBuf);
            free(strBuf);
        }
    }
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-03-24 11:43:13

我已经通过将这一行代码放在空闲(StrBuf)之后进行了调试;(虽然没有重复的空闲(StrBuf)...)

代码语言:javascript
复制
strBuf = NULL;
票数 0
EN

Stack Overflow用户

发布于 2011-03-22 16:24:49

我已经在Galaxy S上测试过了,它在Galaxy S (2.2)上运行良好。我没有在另一台Nexus One上尝试过,以便知道我的Nexus One是否有故障。

而且看起来AssetFileDescriptor不是问题的根源,因为当我没有直接访问资产文件而是访问复制的资产文件时,问题仍然存在。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5137991

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档