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

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 进一步影响运行效率。
解决方案
  1. 将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();
  1. 修复Python侧的潜在问题:
    • 补充非tif/bmp格式文件的分支处理,避免未定义outfile就返回的错误
    • 去掉每次调用都执行的gc.collect(),手动触发全量GC反而会增加不必要的性能开销,PIL本身的资源管理足够应对正常使用场景
    • 可以补充异常捕获逻辑,避免文件读写、处理失败时直接崩溃导致C++侧拿到异常返回值引发内存问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 04:06:04