访问冲突写入位置0x0000000C

2024-10-04 13:23:37 发布

您现在位置:Python中文网/ 问答频道 /正文

我在为一件事挣扎。我试图通过注入的dll从python api调用游戏函数。它有时可以工作,但通常会抛出一个错误:

Exception thrown at 0x1E07F731 (python27.dll) in Soria2.pl.exe: 0xC0000005: Access violation writing location 0x0000000C

以上是来自调试器的日志

我的代码:

 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;
    }

问题部分:

PyObject* mob = PyObject_CallObject(mod, args);

它有时可以工作,但在随机的迭代量(50k、60k、70k等)之后,大多数情况下会抛出上述错误。 我什么都试过了,但还是想不出来。谢谢你的帮助


Tags: pymodif错误argsintpyobjectdll
1条回答
网友
1楼 · 发布于 2024-10-04 13:23:37

我认为@chi是对的:

void Py_DECREF(PyObject *o)

Decrement the reference count for object o. The object must not be NULL; if you aren’t sure that it isn’t NULL, use Py_XDECREF(). If the reference count reaches zero, the object’s type’s deallocation function (which must not be NULL) is invoked.

void Py_XDECREF(PyObject *o)

Decrement the reference count for object o. The object may be NULL, in which case the macro has no effect; otherwise the effect is the same as for Py_DECREF(), and the same warning applies.

Warning

The deallocation function can cause arbitrary Python code to be invoked (e.g. when a class instance with a del() method is deallocated). While exceptions in such code are not propagated, the executed code has free access to all Python global variables. This means that any object that is reachable from a global variable should be in a consistent state before Py_DECREF() is invoked. For example, code to delete an object from a list should copy a reference to the deleted object in a temporary variable, update the list data structure, and then call Py_DECREF() for the temporary variable.

您应该在for循环之后Py_XDECREF(args)

重新阅读文档时,我看到了一个示例:

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);

带着明确的注释:

Note the placement of Py_DECREF(arglist) immediately after the call, before the error check!

因此,正如您在一条评论中所说,您可以将args创建移动到循环中

相关问题 更多 >