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

通过cgo从Go传递OpenCV Mat指针到C++重建时内存泄漏如何解决

问题根本原因

你的内存泄漏核心来自两个常见错误点:

  1. 使用外部数据指针构造cv::Mat时未传入正确的行步长(step)参数,导致Mat内存大小计算错误,拷贝、析构时出现内存异常
  2. 你用到的clone()/copyTo()生成的新Mat对象如果被后续TensorFlow推理逻辑隐式持有所有权,没有随函数执行结束释放,就会出现泄漏

修复方案

方案1:无拷贝方案(性能最优,无内存泄漏)

该方案下C侧的cv::Mat完全不持有数据内存所有权,所有内存由Go侧gocv.Mat管理,C侧仅做访问使用:

Go侧补全传递参数

除了数据指针,你需要将Mat的宽、高、类型、行步长都同步传到C++:

func Detect(detectFrame *gocv.Mat) {
    detectFrameSlice_ptr, _ := detectFrame.DataPtrUint8()
    detectFrame_ptr := unsafe.Pointer(&detectFrameSlice_ptr[0])
    // 新增传递参数
    width := detectFrame.Cols()
    height := detectFrame.Rows()
    matType := detectFrame.Type()
    step := detectFrame.Step()

    C.LIB_predict(detectFrame_ptr, C.int(width), C.int(height), C.int(matType), C.size_t(step))
    // Go侧只要保证detectFrame在LIB_predict执行完成前不被Close/GC回收即可
    // ...
}

C++侧构造无所有权的Mat

用完整参数构造Mat,不需要拷贝数据,函数结束后Mat自动析构,不会释放外部传入的指针内存:

// 先修改头文件声明
void LIB_predict(void* detectFrame_ptr, int width, int height, int matType, size_t step);

void LIB_predict(void* detectFrame_ptr, int width, int height, int matType, size_t step){
    uchar* ptr = static_cast<uchar*>(detectFrame_ptr);
    // 传入step参数,构造的Mat不持有ptr的所有权,析构时不会释放ptr
    cv::Mat inputMat(height, width, matType, ptr, step);
    // 后续推理逻辑直接用inputMat即可,不需要clone/copyTo
    // 函数结束时inputMat作为局部变量自动析构,无内存泄漏
}

方案2:拷贝数据方案(适合C++侧需要长期持有Mat数据的场景)

如果你需要在C++侧保留数据超过本次函数调用的生命周期,就做一次安全拷贝:

void LIB_predict(void* detectFrame_ptr, int width, int height, int matType, size_t step){
    uchar* ptr = static_cast<uchar*>(detectFrame_ptr);
    // 先构造临时无所有权的Mat,再做深拷贝
    cv::Mat tempMat(height, width, matType, ptr, step);
    cv::Mat inputMat = tempMat.clone();
    // tempMat会在构造完inputMat后自动析构,inputMat持有自己的内存
    // 如果你后续把inputMat转Tensor,确保Tensor的生命周期不超过inputMat的生命周期即可
    // 不需要长期持有inputMat的情况下,函数结束后自动析构,不会泄漏
}

额外排查点

如果用了上述方案还是有泄漏,检查两个地方:

  • Go侧的detectFrame是不是调用完Detect函数后没有显式调用Close()方法:gocv的Mat底层是C++分配的内存,不会被Go GC自动回收,必须手动调用Close()释放
  • 你转Tensor的逻辑是不是直接持有了inputMat.data的指针,没有在Tensor销毁时释放对应的内存

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 23:15:02