首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为std::string释放内存时出现异常(试图在UE4中使用YOLO/Darknet )

为std::string释放内存时出现异常(试图在UE4中使用YOLO/Darknet )
EN

Stack Overflow用户
提问于 2020-03-11 01:36:55
回答 2查看 425关注 0票数 0

我正在尝试让YOLO/Darknet在UE4项目中工作。我已经将YOLO构建为C++动态链接库,并将所有依赖项添加到该项目中。它构建得很好,代码的某些部分也正常工作,但我在某个时刻遇到了一个异常,经过几天的努力才弄清楚,我现在很困惑,需要一些帮助。

下面是我从UE4类内部调用创建YOLO检测器类的代码:

代码语言:javascript
复制
YOLO_DataPath = FPaths::ProjectDir() + "Plugins/Stereolabs/Source/YOLO/Data/";
std::string YOLO_DataPathC(TCHAR_TO_UTF8(*YOLO_DataPath));

std::string  NamesFile = YOLO_DataPathC + "obj.names";
std::string  CFGFile = YOLO_DataPathC + "yolo-obj.cfg";
std::string  WeightsFile = YOLO_DataPathC + "yolo-obj.weights";

Detector YOLODetector(CFGFile, WeightsFile);

下面是被调用的构造函数(从'yolo_v2_class.cpp',第130行):

代码语言:javascript
复制
LIB_API Detector::Detector(std::string cfg_filename, std::string weight_filename, int gpu_id) : cur_gpu_id(gpu_id)
{
    wait_stream = 0;
#ifdef GPU
    int old_gpu_index;
    check_cuda( cudaGetDevice(&old_gpu_index) );
#endif

    detector_gpu_ptr = std::make_shared<detector_gpu_t>();
    detector_gpu_t &detector_gpu = *static_cast<detector_gpu_t *>(detector_gpu_ptr.get());

#ifdef GPU
    //check_cuda( cudaSetDevice(cur_gpu_id) );
    cuda_set_device(cur_gpu_id);
    printf(" Used GPU %d \n", cur_gpu_id);
#endif
    network &net = detector_gpu.net;
    net.gpu_index = cur_gpu_id;
    //gpu_index = i;

    _cfg_filename = cfg_filename;
    _weight_filename = weight_filename;

    char *cfgfile = const_cast<char *>(_cfg_filename.c_str());
    char *weightfile = const_cast<char *>(_weight_filename.c_str());

    net = parse_network_cfg_custom(cfgfile, 1, 1);
    if (weightfile) {
        load_weights(&net, weightfile);
    }
    set_batch_network(&net, 1);
    net.gpu_index = cur_gpu_id;
    fuse_conv_batchnorm(net);

    layer l = net.layers[net.n - 1];
    int j;

    detector_gpu.avg = (float *)calloc(l.outputs, sizeof(float));
    for (j = 0; j < NFRAMES; ++j) detector_gpu.predictions[j] = (float*)calloc(l.outputs, sizeof(float));
    for (j = 0; j < NFRAMES; ++j) detector_gpu.images[j] = make_image(1, 1, 3);

    detector_gpu.track_id = (unsigned int *)calloc(l.classes, sizeof(unsigned int));
    for (j = 0; j < l.classes; ++j) detector_gpu.track_id[j] = 1;

#ifdef GPU
    check_cuda( cudaSetDevice(old_gpu_index) );
#endif
}

所有这些代码似乎都运行得很好,但是当它到达构造函数的末尾时,它遇到了一个异常,它似乎正在尝试删除一行中的字符串( xmemory - c:\Program Files (x86)\Microsoft Visual Studio14.0\VC\include\xmemory 0的第132行):

代码语言:javascript
复制
::operator delete(_Ptr);

完整的调用堆栈如下:

代码语言:javascript
复制
[Inline Frame] yolo_cpp_dll.dll!std::_Deallocate(void * _Ptr, unsigned __int64) Line 132
[Inline Frame] yolo_cpp_dll.dll!std::allocator<char>::deallocate(char *) Line 720
[Inline Frame] yolo_cpp_dll.dll!std::_Wrap_alloc<std::allocator<char> >::deallocate(char * _Count, unsigned __int64) Line 987
[Inline Frame] yolo_cpp_dll.dll!std::basic_string<char,std::char_traits<char>,std::allocator<char> >::_Tidy(bool) Line 2258
[Inline Frame] yolo_cpp_dll.dll!std::basic_string<char,std::char_traits<char>,std::allocator<char> >::{dtor}() Line 1017
yolo_cpp_dll.dll!Detector::Detector(std::basic_string<char,std::char_traits<char>,std::allocator<char> > cfg_filename, std::basic_string<char,std::char_traits<char>,std::allocator<char> > weight_filename, int gpu_id) Line 177

从我能找到的关于这个错误的有限信息中,它可能是使用不同的编译器编译的DLL的问题。我现在已经花了几天的时间尝试从零开始编译所有东西的不同版本-从源代码编译UE4,UE4项目,YOLO cpp DLL。我已经尝试了Visual Studio 2015和2017的完全干净的安装,每次都会遇到同样的问题。

有没有人知道这到底是怎么回事?我该如何修复它或解决它呢?

EN

回答 2

Stack Overflow用户

发布于 2020-03-12 08:47:49

简单的方法:永远不要在不同的模块之间传递std::xxx对象。使用原始的C类型。内存应该在分配它的模块中释放。

检测器( const char* cfg_filename,const char* weight_filename,int gpu_id)

硬方法:用相同的编译器/选项编译所有模块(在UE4的情况下特别难)。

票数 0
EN

Stack Overflow用户

发布于 2020-03-12 18:21:20

正如其他人指出的那样,无故障的方法是将代码隐藏在C接口后面,但如果您使用C++,这会对您的接口造成很大限制。因此,如果您想走更艰难的道路,我知道至少有两个项目成功地做到了这一点,您可以进入他们的代码中了解完整的细节。

https://github.com/carla-simulator/carla

  • CARLA

正如这里的大多数评论所指出的,使用相同的编译器和配置,如果您在Visual Studio中打开一个UE4项目,您应该能够检查配置。

然后技巧是静态链接MSVCRT.lib。除非您自己编译UE4,否则它使用发布模式,因此使用/MD编译器标志(参见msvc reference)。下面是CARLA的构建脚本BuildLibCarla.bat#L103-L111中的示例,它使用CMake创建一个静态库,然后这个库被链接到一个UE4插件(dll)中。

Linux

为了完成,我也会添加Linux的细节,因为我希望我在不得不这样做的时候已经在网上找到了这篇文章!

如果您是在Linux上构建的,事情会变得有点复杂,UE4链接到LLVM的libc++运行时,而不是默认的GNU的libstdc++。根据UE4版本的不同,它们使用不同版本的LLVM工具链(它们倾向于相对频繁地更新它)。它们与UE4捆绑在一起,您可以在

二进制文件头和库:Engine/Source/ThirdParty/Linux/LibCxx

  • SDK,
  • Engine/Extras/ThirdPartyNotUE/SDKs/HostLinux/Linux_x64/<clang version>/x86_64-unknown-linux-gnu

然后,要么针对libc++.alibc++abi.a的捆绑版本进行编译和链接,要么编译自己的版本(这就是CARLA做Setup.sh#L37-L58的工作)。请注意,使用从apt install获得的libc++和libc++abi将不起作用,因为这些代码不是用位置独立代码(-fPIC)编译的,您需要将这些代码链接到UE4中的.so。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60623053

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档