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

UE4中调用OpenCV DNN模块释放std::vector内存触发访问违规错误

问题:UE4中调用OpenCV DNN模块触发内存访问冲突错误

环境与背景

使用UE4 4.27.2版本,通过OpenCV 4.5.5版本加载YOLO实现摄像头门检测。UE4的OpenCV插件可正常调用摄像头及执行基础图像处理算法,相关OpenCV代码已通过外部测试,迁移到UE4后使用DNN模块时触发内存错误。

错误信息

Exception thrown at 0x00007FFAFB82551B (UE4Editor-Core.dll) in UE4Editor-Win64-DebugGame.exe: 0xC0000005: Access violation writing location 0x0000000000000010.

最小复现代码

using namespace cv;
using namespace std;

vector<int> outLayers = vector<int>();
vector<String> layersNames = vector<String>();

void FindVerticesProcess()
{
// Line 1310 to 1339
VideoCapture cap;
string srcPath = "E:\\project\\CornerDetector\\src\\";
String videoPath = srcPath + string("IMG_3436.mov");
String modelConfiguration = srcPath + string("yolo-fastest-1.1.cfg");
String modelWeights = srcPath + string("yolo-fastest-1.1_best.weights");
String classesFile = srcPath + string("yolo-fastest-1.1.names");

    cv::dnn::Net doorNet;
    vector<string> classes;
    ifstream ifs(classesFile.c_str());
    string line;
    while (getline(ifs, line)) {
        classes.push_back(line);
    }
    doorNet = cv::dnn::readNetFromDarknet(modelConfiguration, modelWeights);
    doorNet.setPreferableBackend(cv::dnn::DNN_BACKEND_OPENCV);
    doorNet.setPreferableTarget(cv::dnn::DNN_TARGET_OPENCL);
    cap.open(videoPath);
    for (int i = 0; i < 6; i++) {
        Mat frame;
        cap.read(frame);
        Mat blob;
        cv::dnn::blobFromImage(frame, blob, 1 / 255.0, cv::Size(320, 320));
        doorNet.setInput(blob);
        outLayers.resize(0);
        layersNames.resize(0);
        outLayers = doorNet.getUnconnectedOutLayers();
        layersNames = doorNet.getLayerNames();
    }

}

调用栈信息

UE4Editor-Core.dll!00007ffafb82551b()   Unknown
    UE4Editor-Core.dll!00007ffafb826a3e()   Unknown
    UE4Editor-Core.dll!00007ffafb829eb3()   Unknown
    UE4Editor-Core.dll!00007ffafb37893c()   Unknown
    UE4Editor-OpenCV-Win64-DebugGame.dll!operator delete(void * Ptr, unsigned __int64 Size) Line 26 C++
    [External Code] 

> UE4Editor-OpenCV-Win64-DebugGame.dll!FindVerticesProcess() Line 1338  C++
> UE4Editor-OpenCV-Win64-DebugGame.dll!FFindVertices::Run() Line 1412   C++
> [External Code]

现象总结

  • 错误触发位置不固定,doorNet.getUnconnectedOutLayers()和doorNet.getLayerNames()均可能触发,多数在首次循环触发,偶尔在第二、三次循环触发。
  • 删除上述两行代码后,错误消失。
  • 曾找到相似问题但未获得有效解决方案,因无法修改OpenCV原生方法的返回类型,需针对性修复。

修复方案

1. 统一内存分配器

UE4使用自定义内存分配器,而OpenCV默认使用系统分配器,跨模块释放内存会导致冲突。

  • 编译OpenCV时,强制使用UE4的内存分配机制:添加编译宏CV_USE_UE4_ALLOCATOR(若OpenCV支持),或手动替换OpenCV内存分配代码为UE4的FMemory::Malloc/FMemory::Free接口。
  • 确保OpenCV库与UE4插件使用相同的CRT运行时:比如都使用Debug/Release版本的多线程DLL,避免静态CRT与动态CRT混合。

2. 将STL容器改为局部变量

全局的outLayers和layersNames会接收OpenCV分配内存的容器,赋值后跨模块释放内存引发冲突。修改为函数内局部变量:

void FindVerticesProcess()
{
    // ... 原有代码 ...
    for (int i = 0; i < 6; i++) {
        Mat frame;
        cap.read(frame);
        Mat blob;
        cv::dnn::blobFromImage(frame, blob, 1 / 255.0, cv::Size(320, 320));
        doorNet.setInput(blob);
        // 替换为局部变量,确保内存分配释放都在同一模块内
        vector<int> outLayers = doorNet.getUnconnectedOutLayers();
        vector<String> layersNames = doorNet.getLayerNames();
    }
}

3. 禁用OpenCL目标后端

DNN_TARGET_OPENCL的异步执行可能引发内存访问竞态,尤其是DebugGame模式下。暂时切换为CPU目标验证:

doorNet.setPreferableTarget(cv::dnn::DNN_TARGET_CPU);

4. 延长Net对象生命周期

doorNet作为函数局部变量,循环内频繁调用get方法可能导致内部资源引用计数异常。可将doorNet移到函数外(如类成员变量),或用智能指针管理,避免反复创建销毁引发的内存问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 23:31:23