写入位置0x0000000C时发生访问冲突

Access violation writing location 0x0000000C

本文关键字:访问冲突 0x0000000C 位置      更新时间:2023-10-16

我正在为一件事而挣扎。我正试图通过注入的dll从python api调用游戏的函数。它有时有效,但大多会抛出错误:

Soria2.pl.exe中0x1E07F731(python27.dll(处引发异常:0xC0000005:写入位置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等(后抛出上述错误。我什么都试过了,但还是想不通:/感谢你的帮助。

我认为@chi是对的:

无效Py_DECREF(PyObject*o(

减少对象o的引用计数。该对象不能为NULL;如果您不确定它不是NULL,请使用Py_XDECREF((。如果引用计数达到零,则调用对象类型的释放函数(不能为NULL(。

无效Py_XDECREF(PyObject*o(

减少对象o的引用计数。对象可能为NULL,在这种情况下,宏无效;否则效果与Py_DECREF((相同,并应用相同的警告。

警告

deallocation函数可以导致调用任意Python代码(例如,当具有del((方法的类实例被deallocation时(。虽然此类代码中的异常不会传播,但执行的代码可以自由访问所有Python全局变量。这意味着,在调用Py_DECREF((之前,可以从全局变量访问的任何对象都应该处于一致状态。例如,从列表中删除对象的代码应该在临时变量中复制对已删除对象的引用,更新列表数据结构,然后为临时变量调用Py_DECREF((。

您应该在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);

有一个明确的注释:

注意Py_DECREF(arglist(在调用之后、错误检查之前的位置!

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