与opencv链接时内存泄漏

Posted

技术标签:

【中文标题】与opencv链接时内存泄漏【英文标题】:Memory leak when linking against opencv 【发布时间】:2017-01-09 07:58:05 【问题描述】:

我正在链接一个库与 opencv 库。我注意到,当我为该库运行单元测试可执行文件(使用 GTest)时,valgrind 报告内存泄漏/条件跳转或移动取决于未初始化的值,即使测试根本没有做任何事情(只是空测试方法)。

我将该问题追溯到我的 CMakeLists.txt 中的一行 - 当我删除与 opencv 的链接时,内存泄漏就消失了。这是相关的sn-p:

find_package(OpenCV REQUIRED)

set(libImageSources src/SourceImageFile.cpp)

add_library(image SHARED $libImageSources)

# removing this line fixes the leak:
target_link_libraries(image $OpenCV_LIBS)

否则在运行空单元测试时,我会收到如下错误:

==18681== Memcheck, a memory error detector
==18681== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==18681== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==18681== Command: ./image_test /Users/max/Documents/playground/cpp/image-server/tests
==18681==
==18681== Conditional jump or move depends on uninitialised value(s)
==18681==    at 0x7FFF5FC24A27: bcmp (in /usr/lib/dyld)
==18681==    by 0x7FFF5FC11904: ImageLoaderMachO::validateFirstPages(linkedit_data_command const*, int, unsigned char const*, unsigned long, long long, ImageLoader::LinkContext const&) (in /usr/lib/dyld)
==18681==    by 0x7FFF5FC16B7A: ImageLoaderMachOCompressed::instantiateFromFile(char const*, int, unsigned char const*, unsigned long, unsigned long long, unsigned long long, stat const&, unsigned int, unsigned int, linkedit_data_command const*, encryption_info_command const*, ImageLoader::LinkContext const&) (in /usr/lib/dyld)
==18681==    by 0x7FFF5FC10A6E: ImageLoaderMachO::instantiateFromFile(char const*, int, unsigned char const*, unsigned long long, unsigned long long, stat const&, ImageLoader::LinkContext const&) (in /usr/lib/dyld)
==18681==    by 0x7FFF5FC038C2: dyld::loadPhase6(int, stat const&, char const*, dyld::LoadContext const&) (in /usr/lib/dyld)
==18681==    by 0x7FFF5FC08468: dyld::loadPhase5(char const*, char const*, dyld::LoadContext const&, std::__1::vector<char const*, std::__1::allocator<char const*> >*) (in /usr/lib/dyld)
==18681==    by 0x7FFF5FC08188: dyld::loadPhase4(char const*, char const*, dyld::LoadContext const&, std::__1::vector<char const*, std::__1::allocator<char const*> >*) (in /usr/lib/dyld)
==18681==    by 0x7FFF5FC07EED: dyld::loadPhase3(char const*, char const*, dyld::LoadContext const&, std::__1::vector<char const*, std::__1::allocator<char const*> >*) (in /usr/lib/dyld)
==18681==    by 0x7FFF5FC07642: dyld::loadPhase1(char const*, char const*, dyld::LoadContext const&, std::__1::vector<char const*, std::__1::allocator<char const*> >*) (in /usr/lib/dyld)
==18681==    by 0x7FFF5FC0347A: dyld::loadPhase0(char const*, char const*, dyld::LoadContext const&, std::__1::vector<char const*, std::__1::allocator<char const*> >*) (in /usr/lib/dyld)
==18681==    by 0x7FFF5FC0315E: dyld::load(char const*, dyld::LoadContext const&) (in /usr/lib/dyld)
==18681==    by 0x7FFF5FC08705: dyld::libraryLocator(char const*, bool, char const*, ImageLoader::RPathChain const*) (in /usr/lib/dyld)
==18681==
==18681== Use of uninitialised value of size 8
==18681==    at 0x7FFF5FC24A3F: bcmp (in /usr/lib/dyld)
==18681==    by 0x7FFF5FC11904: ImageLoaderMachO::validateFirstPages(linkedit_data_command const*, int, unsigned char const*, unsigned long, long long, ImageLoader::LinkContext const&) (in /usr/lib/dyld)
==18681==    by 0x7FFF5FC16B7A: ImageLoaderMachOCompressed::instantiateFromFile(char const*, int, unsigned char const*, unsigned long, unsigned long long, unsigned long long, stat const&, unsigned int, unsigned int, linkedit_data_command const*, encryption_info_command const*, ImageLoader::LinkContext const&) (in /usr/lib/dyld)
==18681==    by 0x7FFF5FC10A6E: ImageLoaderMachO::instantiateFromFile(char const*, int, unsigned char const*, unsigned long long, unsigned long long, stat const&, ImageLoader::LinkContext const&) (in /usr/lib/dyld)
==18681==    by 0x7FFF5FC038C2: dyld::loadPhase6(int, stat const&, char const*, dyld::LoadContext const&) (in /usr/lib/dyld)
==18681==    by 0x7FFF5FC08468: dyld::loadPhase5(char const*, char const*, dyld::LoadContext const&, std::__1::vector<char const*, std::__1::allocator<char const*> >*) (in /usr/lib/dyld)
==18681==    by 0x7FFF5FC08188: dyld::loadPhase4(char const*, char const*, dyld::LoadContext const&, std::__1::vector<char const*, std::__1::allocator<char const*> >*) (in /usr/lib/dyld)
==18681==    by 0x7FFF5FC07EED: dyld::loadPhase3(char const*, char const*, dyld::LoadContext const&, std::__1::vector<char const*, std::__1::allocator<char const*> >*) (in /usr/lib/dyld)
==18681==    by 0x7FFF5FC07642: dyld::loadPhase1(char const*, char const*, dyld::LoadContext const&, std::__1::vector<char const*, std::__1::allocator<char const*> >*) (in /usr/lib/dyld)
==18681==    by 0x7FFF5FC0347A: dyld::loadPhase0(char const*, char const*, dyld::LoadContext const&, std::__1::vector<char const*, std::__1::allocator<char const*> >*) (in /usr/lib/dyld)
==18681==    by 0x7FFF5FC0315E: dyld::load(char const*, dyld::LoadContext const&) (in /usr/lib/dyld)
==18681==    by 0x7FFF5FC08705: dyld::libraryLocator(char const*, bool, char const*, ImageLoader::RPathChain const*) (in /usr/lib/dyld)
==18681==
==18681== Use of uninitialised value of size 8
==18681==    at 0x7FFF5FC24A44: bcmp (in /usr/lib/dyld)
==18681==    by 0x7FFF5FC11904: ImageLoaderMachO::validateFirstPages(linkedit_data_command const*, int, unsigned char const*, unsigned long, long long, ImageLoader::LinkContext const&) (in /usr/lib/dyld)
==18681==    by 0x7FFF5FC16B7A: ImageLoaderMachOCompressed::instantiateFromFile(char const*, int, unsigned char const*, unsigned long, unsigned long long, unsigned long long, stat const&, unsigned int, unsigned int, linkedit_data_command const*, encryption_info_command const*, ImageLoader::LinkContext const&) (in /usr/lib/dyld)
==18681==    by 0x7FFF5FC10A6E: ImageLoaderMachO::instantiateFromFile(char const*, int, unsigned char const*, unsigned long long, unsigned long long, stat const&, ImageLoader::LinkContext const&) (in /usr/lib/dyld)
==18681==    by 0x7FFF5FC038C2: dyld::loadPhase6(int, stat const&, char const*, dyld::LoadContext const&) (in /usr/lib/dyld)
==18681==    by 0x7FFF5FC08468: dyld::loadPhase5(char const*, char const*, dyld::LoadContext const&, std::__1::vector<char const*, std::__1::allocator<char const*> >*) (in /usr/lib/dyld)
==18681==    by 0x7FFF5FC08188: dyld::loadPhase4(char const*, char const*, dyld::LoadContext const&, std::__1::vector<char const*, std::__1::allocator<char const*> >*) (in /usr/lib/dyld)
==18681==    by 0x7FFF5FC07EED: dyld::loadPhase3(char const*, char const*, dyld::LoadContext const&, std::__1::vector<char const*, std::__1::allocator<char const*> >*) (in /usr/lib/dyld)
==18681==    by 0x7FFF5FC07642: dyld::loadPhase1(char const*, char const*, dyld::LoadContext const&, std::__1::vector<char const*, std::__1::allocator<char const*> >*) (in /usr/lib/dyld)
==18681==    by 0x7FFF5FC0347A: dyld::loadPhase0(char const*, char const*, dyld::LoadContext const&, std::__1::vector<char const*, std::__1::allocator<char const*> >*) (in /usr/lib/dyld)
==18681==    by 0x7FFF5FC0315E: dyld::load(char const*, dyld::LoadContext const&) (in /usr/lib/dyld)
==18681==    by 0x7FFF5FC08705: dyld::libraryLocator(char const*, bool, char const*, ImageLoader::RPathChain const*) (in /usr/lib/dyld)
==18681==
==18681== Conditional jump or move depends on uninitialised value(s)
==18681==    at 0x7FFF5FC11907: ImageLoaderMachO::validateFirstPages(linkedit_data_command const*, int, unsigned char const*, unsigned long, long long, ImageLoader::LinkContext const&) (in /usr/lib/dyld)
==18681==    by 0x7FFF5FC16B7A: ImageLoaderMachOCompressed::instantiateFromFile(char const*, int, unsigned char const*, unsigned long, unsigned long long, unsigned long long, stat const&, unsigned int, unsigned int, linkedit_data_command const*, encryption_info_command const*, ImageLoader::LinkContext const&) (in /usr/lib/dyld)
==18681==    by 0x7FFF5FC10A6E: ImageLoaderMachO::instantiateFromFile(char const*, int, unsigned char const*, unsigned long long, unsigned long long, stat const&, ImageLoader::LinkContext const&) (in /usr/lib/dyld)
==18681==    by 0x7FFF5FC038C2: dyld::loadPhase6(int, stat const&, char const*, dyld::LoadContext const&) (in /usr/lib/dyld)
==18681==    by 0x7FFF5FC08468: dyld::loadPhase5(char const*, char const*, dyld::LoadContext const&, std::__1::vector<char const*, std::__1::allocator<char const*> >*) (in /usr/lib/dyld)
==18681==    by 0x7FFF5FC08188: dyld::loadPhase4(char const*, char const*, dyld::LoadContext const&, std::__1::vector<char const*, std::__1::allocator<char const*> >*) (in /usr/lib/dyld)
==18681==    by 0x7FFF5FC07EED: dyld::loadPhase3(char const*, char const*, dyld::LoadContext const&, std::__1::vector<char const*, std::__1::allocator<char const*> >*) (in /usr/lib/dyld)
==18681==    by 0x7FFF5FC07642: dyld::loadPhase1(char const*, char const*, dyld::LoadContext const&, std::__1::vector<char const*, std::__1::allocator<char const*> >*) (in /usr/lib/dyld)
==18681==    by 0x7FFF5FC0347A: dyld::loadPhase0(char const*, char const*, dyld::LoadContext const&, std::__1::vector<char const*, std::__1::allocator<char const*> >*) (in /usr/lib/dyld)
==18681==    by 0x7FFF5FC0315E: dyld::load(char const*, dyld::LoadContext const&) (in /usr/lib/dyld)
==18681==    by 0x7FFF5FC08705: dyld::libraryLocator(char const*, bool, char const*, ImageLoader::RPathChain const*) (in /usr/lib/dyld)
==18681==    by 0x7FFF5FC0E85D: ImageLoader::recursiveLoadLibraries(ImageLoader::LinkContext const&, bool, ImageLoader::RPathChain const&) (in /usr/lib/dyld)
==18681==
[==========] Running 1 test from 1 test case.
[----------] Global test environment set-up.
[----------] 1 test from ImageProcessingConfigurationService
[ RUN      ] ImageProcessingConfigurationService.evaluateConfigurationFile
[       OK ] ImageProcessingConfigurationService.evaluateConfigurationFile (13 ms)
[----------] 1 test from ImageProcessingConfigurationService (28 ms total)

[----------] Global test environment tear-down
[==========] 1 test from 1 test case ran. (114 ms total)
[  PASSED  ] 1 test.
==18681==
==18681== HEAP SUMMARY:
==18681==     in use at exit: 1,346,030 bytes in 1,453 blocks
==18681==   total heap usage: 2,926 allocs, 1,473 frees, 3,045,052 bytes allocated
==18681==
==18681== LEAK SUMMARY:
==18681==    definitely lost: 10,580 bytes in 137 blocks
==18681==    indirectly lost: 10,032 bytes in 152 blocks
==18681==      possibly lost: 9,568 bytes in 183 blocks
==18681==    still reachable: 43,598 bytes in 520 blocks
==18681==         suppressed: 1,272,252 bytes in 461 blocks
==18681== Rerun with --leak-check=full to see details of leaked memory
==18681==
==18681== For counts of detected and suppressed errors, rerun with: -v
==18681== Use --track-origins=yes to see where uninitialised values come from
==18681== ERROR SUMMARY: 36 errors from 4 contexts (suppressed: 0 from 0)

编译器是 clang++ Apple LLVM 版本 7.3.0 (clang-703.0.31),OS X El Capitan (10.11.1)。

其他人遇到过这样的问题吗?看起来东西仍然有效,但错误会产生我宁愿忽略的噪音,我不确定我是否可以解决根本原因。

【问题讨论】:

... that valgrind reports a memory leak/invalid free - 在错误日志中,我在动态加载程序中只看到内存泄漏加上Conditional jump or move depends on uninitialised value。没有“无效免费”左右。 @Tsyvarev 没错,我的意思是jump on unitialized value 消息,抱歉。我认为这很可能是 valgrind 的误报,我使用 OS X 分析器来检查内存泄漏,看起来还不错。 @usr1234567 我在调试时认为它与 CMake 无关,但感谢您的指点。 【参考方案1】:

这个问题似乎是 valgrind 报告的误报,我可以忽略它,因为它不是由代码引起的。

我尝试了(在撰写本文时)最新的valgrind suppressions file for macOS,但它对我不起作用,问题仍然存在。

我让valgrind dump the suppressions 需要忽略这个错误,使用如下命令:

valgrind --leak-check=full --show-reachable=yes --error-limit=no --gen-suppressions=all --log-file=l.log ./image_test

然后使用a tool to parse the log output(awk 脚本对我不起作用,因为它包含语法错误,我使用了 perl 版本)到抑制文件中:

cat l.log | ./parse_valgrind_suppressions.pl > s.supp

现在使用生成的抑制文件运行测试会忽略内存泄漏:

valgrind --suppressions=./s.supp ./image_test

【讨论】:

以上是关于与opencv链接时内存泄漏的主要内容,如果未能解决你的问题,请参考以下文章

OpenCv - 从网络摄像头捕获帧时发生内存泄漏

OpenCV 3.0 的问题 - 录制视频内存泄漏

OpenCV - cvExtractSURF 导致内存泄漏?

内存泄漏(OpenCV + QML)

为啥 OpenCV Mat 会造成内存泄漏?

在 OpenCV 应用程序中,我如何识别内存泄漏的来源并修复它?