C++循环调用Python函数运行数小时后速度变慢问题求助
问题原因
- 最核心的错误是你在for循环内反复调用
Py_Initialize()和Py_Finalize():Python官方明确说明Py_Finalize()无法完全释放解释器占用的所有资源,循环中反复初始化/销毁解释器会产生持续累积的内存泄漏、资源残留,运行时间越长性能下降越明显。 - 存在严重的引用计数泄漏:你提供的C++代码中,调用Python函数得到的返回值
pValue完全没有执行Py_DECREF释放,每次循环都会泄漏至少一个PyObject对象的内存,累积到一定程度就会导致调用效率持续下降。同时代码中还存在语法错误:Py_DECREF(语句未补全,缺少释放pValue的逻辑。 - 重复导入模块开销大:你每次循环都重新执行
PyImport_Import导入脚本,即使不反复重启解释器,不必要的重复导入也会产生额外开销,加上资源残留的影响,导入速度会越来越慢。 - 字符串指针使用有隐患:
_PyUnicode_AsString返回的是Python内部管理的字符串指针,你直接赋值给antwort后如果后续释放了pValue,该指针会变成野指针,可能引发内存 corruption 进一步影响运行效率。
解决方案
- 将Python初始化、模块导入、函数获取逻辑移到循环外,全局只执行一次:
// 循环外提前执行,只跑一次 PyObject *pFunc = NULL; Py_Initialize(); PyObject* fname = PyUnicode_FromString("TEST"); PyObject* module = PyImport_Import(fname); pFunc = PyObject_GetAttrString(module, "umwandeln"); Py_DECREF(fname); Py_DECREF(module); // 循环内只保留调用逻辑 for (...) { // 你的业务循环 char *antwort = NULL; PyObject *pArgs = PyTuple_Pack(1, PyUnicode_FromString(filename)); PyObject *pValue = PyObject_CallObject(pFunc, pArgs); const char* result = _PyUnicode_AsString(pValue); // 这里要复制字符串,不能直接存指针 antwort = strdup(result); // 及时释放本次循环产生的对象 Py_DECREF(pArgs); Py_DECREF(pValue); // 后续业务逻辑,使用完antwort记得free } // 程序退出前再销毁解释器 Py_DECREF(pFunc); Py_Finalize();
- 修复Python侧的潜在问题:
- 补充非tif/bmp格式文件的分支处理,避免未定义
outfile就返回的错误 - 去掉每次调用都执行的
gc.collect(),手动触发全量GC反而会增加不必要的性能开销,PIL本身的资源管理足够应对正常使用场景 - 可以补充异常捕获逻辑,避免文件读写、处理失败时直接崩溃导致C++侧拿到异常返回值引发内存问题
- 补充非tif/bmp格式文件的分支处理,避免未定义
内容的提问来源于stack exchange,提问作者GT2
相关产品推荐
相关产品推荐

