SIGSEGV:JCC库代码中的分段错误

时间:2013-05-09 17:53:42

标签: python segmentation-fault java jcc

我正在使用JCC Python-Java桥,并且大部分都可以使用它。但是,我收到以下错误:

  

JRE版本:7.0_17-b02

     

Java VM:Java HotSpot(TM)客户端VM(23.7-b01混合模式linux-x86)

     

有问题的框架:

     

C [_ciasliveschema.so + 0x21e75c] boxJObject(_typeobject *,_ object *,java :: lang :: Object *)+ 0x22c

堆栈转储如下:

  

堆叠:[0xbfbe5000,0xbfc35000],sp = 0xbfc33820,可用空间= 314k

     

原生帧:(J =已编译的Java代码,j =已解释,Vv = VM代码,C =本机代码)

     

C [_ciasliveschema.so + 0x21e75c] boxJObject(_typeobject *,_ object *,java :: lang :: Object *)+ 0x22c

     

C [_ciasliveschema.so + 0x221977] boxObject(_typeobject *,_ object *,java :: lang :: Object *)+ 0x27

     

C [_ciasliveschema.so + 0x225149] _parseArgs(_object * ,unsigned int,char ,...)+ 0x2f69

     

C [_ciasliveschema.so + 0x17e21c] schema :: util :: t_IndividualCaster_asMessage   (schema :: util :: t_IndividualCaster *,_ object *)+ 0xac

     

C [python + 0x8bda4] PyEval_EvalFrameEx + 0x6494

     

C [python + 0x8ccb1] PyEval_EvalCodeEx + 0x871

     

C [python + 0xe0a0c] fileno @@ GLIBC_2.0 + 0xe0a0c

     

C [python + 0x143b5] PyObject_Call + 0x45

     

C [python + 0x1b107] fileno @@ GLIBC_2.0 + 0x1b107

     

C [python + 0x143b5] PyObject_Call + 0x45

     

C [python + 0x84a72] PyEval_CallObjectWithKeywords + 0x42

     

C [python + 0x1eec1] PyInstance_New + 0x71

     

C [python + 0x143b5] PyObject_Call + 0x45

     

C [python + 0x86923] PyEval_EvalFrameEx + 0x1013

     

C [python + 0x8b347] PyEval_EvalFrameEx + 0x5a37

     

C [python + 0x8ccb1] PyEval_EvalCodeEx + 0x871

     

C [python + 0x8cd47] PyEval_EvalCode + 0x57

boxJObject函数的代码如下:

static int boxJObject(PyTypeObject *type, PyObject *arg,
                      java::lang::Object *obj)
{
    if (arg == Py_None)
    {
        if (obj != NULL)
            *obj = Object(NULL);
    }
    else if (PyObject_TypeCheck(arg, &PY_TYPE(Object)))
    {
        if (type != NULL && !is_instance_of(arg, type))
            return -1;

        if (obj != NULL)
            *obj = ((t_Object *) arg)->object;
    }
    else if (PyObject_TypeCheck(arg, &PY_TYPE(FinalizerProxy)))
    {
        arg = ((t_fp *) arg)->object;
        if (PyObject_TypeCheck(arg, &PY_TYPE(Object)))
        {
            if (type != NULL && !is_instance_of(arg, type))
                    return -1;

            if (obj != NULL)
                *obj = ((t_Object *) arg)->object;
        }
        else
            return -1;
    }
    else
        return 1;

    return 0;
}

以下列方式调用:

int result = boxJObject(type, arg, obj);

另外,我修改了jcc.cpp:initVM()方法的以下部分:

    if (JNI_CreateJavaVM(&vm, (void **) &vm_env, &vm_args) < 0)
    {
        for (unsigned int i = 0; i < nOptions; i++)
            delete vm_options[i].optionString;


        PyErr_Format(PyExc_ValueError,
                     "An error occurred while creating Java VM");
        return NULL;
    }

如下:

    vm_args.nOptions = nOptions;
    vm_args.ignoreUnrecognized = JNI_FALSE;
    vm_args.options = vm_options;

    vmInitSuccess = JNI_CreateJavaVM(&vm, (void **) &vm_env, &vm_args);
    if (vmInitSuccess < 0)
    {
        for (unsigned int i = 0; i < nOptions; i++)
            delete vm_options[i].optionString;

        //Set up basic error message
        sprintf(strVMInitSuccess, "%d", vmInitSuccess);
        strcpy(strVMError, "An error occurred while creating Java VM (No Exception): ");
        strcat(strVMError, strVMInitSuccess);

        //Get exception if there is one
        if((exc = vm_env->ExceptionOccurred()))
        {
            //Clear the exception since we have it now
            vm_env->ExceptionClear();
            //Get the getMessage() method
            if ((java_class = vm_env->FindClass ("java/lang/Throwable")))
            {
                if ((method = vm_env->GetMethodID(java_class, "getMessage", "()Ljava/lang/String;")))
                {
                    int size;
                    strExc = static_cast<jstring>(vm_env->CallObjectMethod(exc, method)); 
                    charExc = vm_env->GetStringUTFChars(strExc, NULL);
                    size = sizeof(strVMError) + sizeof(charExc);
                    char strVMException[size];
                    strcpy(strVMException, "An error occurred while creating Java VM (Exception): ");
                    strcat(strVMException, charExc);
                    PyErr_Format(PyExc_ValueError, strVMException);
                    return NULL;
                }
            }
        }
        PyErr_Format(PyExc_ValueError, strVMError);
        return NULL;
    }

这是为了在发生错误时尝试从JCC返回更详细的错误消息,因此可能是错误的来源(尽管上面的段错误和堆栈跟踪建议不然)。

最后,我目前正在Python中调用initVM()方法,如下所示:

self.__cslschemalib = ciasliveschema.initVM(classpath=ciasliveschema.CLASSPATH)

但是,当我尝试按如下方式调用方法时(增加可用内存量):

self.__cslschemalib = ciasliveschema.initVM(classpath=ciasliveschema.CLASSPATH, initialheap='512m', maxheap='2048m', maxstack='2048m', vmargs='-Xcheck:jni,-verbose:jni,-verbose:gc')

我收到以下错误:

  

JRE版本:7.0_17-b02   Java VM:Java HotSpot(TM)客户端VM(23.7-b01混合模式linux-x86)   有问题的框架:   C 0x00000000

堆栈跟踪:

  

堆叠:[0xbf6e0000,0xbf8e0000],sp = 0xbf8dd580,可用空间= 2037k

有什么建议吗?

1 个答案:

答案 0 :(得分:0)

问题已经解决。实际上在调用上面的boxJObject方法时出现了问题:

if (boxObject(NULL, arg, obj) < 0) return -1;

这是JCC源代码的functions.cpp中的_parseArgs函数。

出现问题是因为(至少从这个函数的快速扫描中),_parseArgs检查是否传递了更多 args而不是方法接受,但是没有检查是否存在更少的args已经通过。

在我的Python代码中调用IndividualCaster()。asMessage()方法时,当方法实际需要两个时,我只传递了一个参数。虽然我没有在_parseArgs方法中找到错误的确切来源,但我已经在Python代码中更正了调用,因此它现在需要正确数量的args,并且不再发生seg错误。