SIGSEGV: ошибка сегментации в коде библиотеки JCC

Я использую мост JCC Python-Java, и по большей части он работает. Однако я получаю следующую ошибку:

Версия JRE: 7.0_17-b02

Java VM: клиентская виртуальная машина Java HotSpot ™ (смешанный режим 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 при возникновении ошибок, поэтому возможно, что это является источником ошибки (хотя ошибка segfault и трассировка стека выше предполагают иное).

Наконец, в настоящее время я вызываю метод initVM () из Python следующим образом:

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) Клиентская виртуальная машина (смешанный режим 23.7-b01 linux-x86) Проблемный кадр: C 0x00000000

И трассировка стека:

Стек: [0xbf6e0000,0xbf8e0000], sp=0xbf8dd580, свободное пространство =2037k

Какие-либо предложения?

1 ответ

Решение

Проблема была решена. Проблема фактически возникла при вызове вышеупомянутого метода boxJObject:

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

Это функция _parseArgs в functions.cpp исходного кода JCC.

Проблема возникла из-за того, что (по крайней мере, после быстрого сканирования этой функции) _parseArgs проверяет, было ли передано больше аргументов, чем принимает метод, но не проверяет случай, когда было передано меньше аргументов.

При вызове метода IndividualCaster(). AsMessage() в моем коде Python я передавал только один аргумент, когда метод фактически принимает два. Хотя я не нашел точного источника ошибки в методе _parseArgs, я исправил вызов в своем коде Python, чтобы он теперь принимал правильное количество аргументов, и ошибка сегмента больше не возникает.

Другие вопросы по тегам