Место записи нарушения прав доступа 0x0000000C - PullRequest
0 голосов
/ 14 июля 2020

Я борюсь с одним. Я пытаюсь вызвать функции игры из python api через внедренную dll. Иногда это срабатывает, но чаще всего вызывает ошибку:

Исключение, выброшенное на 0x1E07F731 (python27.dll) в Soria2.pl.exe: 0xC0000005: место записи нарушения прав доступа 0x0000000 C

это журнал от отладчика.

Мой код:

 std::vector<int> mobList()
    {
        PyObject* mod = PyObject_GetAttrString(PyImport_AddModule("player"), "GetCharacterDistance");
        PyObject* mod2 = PyObject_GetAttrString(PyImport_AddModule("chr"), "GetInstanceType");
        PyObject* args = PyTuple_New(1);
        std::vector<int> mobs;
    
        for (int i = 1; i < 100000; i++) {
            try {
                PyTuple_SetItem(args, 0, PyInt_FromLong(i));
                PyObject* mob = PyObject_CallObject(mod, args);
                if (PyInt_AsLong(mob) > 0 && PyInt_AsLong(mob) < 400) {
                    PyObject* enemy = PyObject_CallObject(mod2, args);
                    if (PyInt_AsLong(enemy) == 0) {
                        mobs.push_back(i);
                    }
                    if (enemy != NULL) {
                        Py_DECREF(enemy);
                    }
                }
                if (mob != NULL) {
                    Py_DECREF(mob);
                }
                Py_XDECREF(args);
            }
            catch (int e) {
                std::cout << e << std::endl;
            }
        }
        return mobs;
    }

и проблемные c часть:

PyObject* mob = PyObject_CallObject(mod, args);

Иногда работает, но в основном бросает упомянутая ошибка после случайного количества итераций (50k, 60k, 70k et c). Я все перепробовал и до сих пор не могу понять: / Благодарю за любую помощь.

1 Ответ

1 голос
/ 15 июля 2020

Я думаю, что @chi прав:

void Py_DECREF (PyObject * o)

Уменьшите счетчик ссылок для объекта o. Объект не должен быть NULL; если вы не уверены, что это не NULL, используйте Py_XDECREF (). Если счетчик ссылок достигает нуля, вызывается функция освобождения типа объекта (которая не должна быть NULL).

void Py_XDECREF (PyObject * o)

Уменьшает счетчик ссылок для объекта o. Объект может иметь значение NULL, и в этом случае макрос не действует; в противном случае эффект такой же, как и для Py_DECREF (), и применяется то же предупреждение.

Предупреждение

Функция освобождения может вызвать вызов произвольного кода Python (например, когда освобождается экземпляр класса с методом del ()). Хотя исключения в таком коде не распространяются, исполняемый код имеет свободный доступ ко всем глобальным переменным Python. Это означает, что любой объект, доступный из глобальной переменной, должен находиться в согласованном состоянии до вызова Py_DECREF (). Например, код для удаления объекта из списка должен скопировать ссылку на удаленный объект во временной переменной, обновить структуру данных списка, а затем вызвать Py_DECREF () для временной переменной.

Вы должны Py_XDECREF(args) после for l oop.

Перечитывая документы, я вижу пример:

arglist = Py_BuildValue("(l)", eventcode);
result = PyObject_CallObject(my_callback, arglist);
Py_DECREF(arglist);
if (result == NULL)
    return NULL; /* Pass error back */
/* Here maybe use the result */
Py_DECREF(result);

С явным примечанием:

Обратите внимание на размещение Py_DECREF (arglist) сразу после вызова, перед проверкой ошибок!

Итак, как вы сказали в одном из своих комментариев, вы можете переместить args создание внутри l oop.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...