You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多子解释器通过Python C API导入特定模块时触发内存损坏错误

问题现象

我编写了单线程C++代码,借助Python C API启动两个子解释器Sub1和Sub2,随后在两个子解释器中加载模块M。当M导入urllib.request、yaml等特定模块时,若Sub1已完成M的导入,Sub2导入M会触发内存损坏错误;但如果M导入的是urllib、base64、os等模块则可正常运行。

C++代码实现

Py_Initialize();

PyThreadState *tstate_main, *tstate_s1, *tstate_s2;

tstate_main = PyThreadState_Get();
std::cerr << "tstate_main: " << tstate_main << std::endl;

//PyGILState_STATE gstate = PyGILState_Ensure();
PyInterpreterConfig config_s1 = {
    .use_main_obmalloc = 0,
    .allow_fork = 0,
    .allow_exec = 0,
    .allow_threads = 0,
    .allow_daemon_threads = 0,
    .check_multi_interp_extensions = 1,
    .gil = PyInterpreterConfig_OWN_GIL,
};
tstate_s1 = NULL;
PyStatus status_s1 = Py_NewInterpreterFromConfig(&tstate_s1, &config_s1);
std::cerr << "tstate_s1: " << tstate_s1 << std::endl;
std::string sysPathCmd1 = "import sys\nsys.path.append('" + cwd + "')";
PyRun_SimpleString(sysPathCmd1.c_str());
PyObject* bytecode1 = Py_CompileString(module_code1, "test_module1", Py_file_input);
PyObject* pModule1 = PyImport_ExecCodeModule("test_module1", bytecode1);
if(!pModule1) {
    std::cerr << "Error on module import:" << std::endl;
    PyErr_Print();
    return -1;
}
PyObject* pFunc1 = PyObject_GetAttrString(pModule1, "test_call");
PyObject* pData1 = PyUnicode_FromString("hello");
PyObject* pArgs1 = PyTuple_Pack(1, pData1);
PyObject* pResult1 = PyObject_CallObject(pFunc1, pArgs1);

PyEval_RestoreThread(tstate_main);

//PyGILState_STATE gstate = PyGILState_Ensure();
PyInterpreterConfig config_s2 = {
    .use_main_obmalloc = 0,
    .allow_fork = 0,
    .allow_exec = 0,
    .allow_threads = 0,
    .allow_daemon_threads = 0,
    .check_multi_interp_extensions = 1,
    .gil = PyInterpreterConfig_OWN_GIL,
};
tstate_s2 = NULL;
PyStatus status_s2 = Py_NewInterpreterFromConfig(&tstate_s2, &config_s2);
std::cerr << "tstate_s2: " << tstate_s2 << std::endl;
std::string sysPathCmd2 = "import sys\nsys.path.append('" + cwd + "')";
PyRun_SimpleString(sysPathCmd2.c_str());
PyObject* bytecode2 = Py_CompileString(module_code2, "test_module2", Py_file_input);
PyObject* pModule2 = PyImport_ExecCodeModule("test_module2", bytecode2);
PyObject* pFunc2 = PyObject_GetAttrString(pModule2, "test_call");
PyObject* pData2 = PyUnicode_FromString("");
PyObject* pArgs2 = PyTuple_Pack(1, pData2);
PyObject* pResult2 = PyObject_CallObject(pFunc2, pArgs2);

PyEval_RestoreThread(tstate_main);

Python测试代码

# import yaml # ERROR
# import urllib.request # ERROR
# import urllib # NO ERROR
# import os # NO ERROR
# import os.path # NO ERROR
# import base64 # NO ERROR

def test_call(data):
    print("Called")

内容的提问来源于stack exchange,提问作者Michele Agostini

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 23:23:13