在Win32上增强icu u32_regex内存泄漏/缓存
boost with icu u32_regex memory leak / cache on Win32
当使用启用可选ICU支持的boost regex类时(详细信息请参阅boost文档),我似乎得到了内存泄漏,或者更确切地说是某种内存缓存发生,我似乎无法重置/清理。
有没有其他人看到这个,也许知道一种清除缓存的方法,以便boost单元测试框架不会报告内存泄漏?
我的问题的细节是:-
ICU version 4.6.0
(Built using supplied vs2010 solution in debug and release configuration)
Boost version 1.45
(built with command "bjam variant=debug,release threading=multi link=shared stage" since standard distribution does not include icu support in regex)
OS Windows 7
Compiler MSVC 10 (Visual Studio 2010 Premium)
虽然我确实尝试了一个boost 1.42和icu 4.2.1,我碰巧在我的系统上建立了相同的结果,所以不要认为这是一个问题,可以通过更改为最新版本的boost 1.47 icu 4.8.1来解决。
编译以下代码(Test.cpp):-#define BOOST_TEST_MAIN //Ask boost unit test framework to create a main for us
#define BOOST_ALL_DYN_LINK //Ask boost to link to dynamic library rather than purely header support where appropriate
#include <boost/test/auto_unit_test.hpp>
#include <boost/regex.hpp>
#include <boost/regex/icu.hpp> //We use icu extensions to regex to support unicode searches on utf-8
#include <unicode/uclean.h> //We want to be able to clean up ICU cached objects
BOOST_AUTO_TEST_CASE( standard_regex )
{
boost::regex re( "\d{3}");
}
BOOST_AUTO_TEST_CASE( u32_regex )
{
boost::u32regex re( boost::make_u32regex("\d{3}"));
u_cleanup(); //Ask the ICU library to clean up any cached memory
}
可以通过以下命令行编译:-
C:>cl test.cpp /I[BOOST HEADERS PATH] /I[ICU HEADERS] /EHsc /MDd -link /LIBPATH:[BOOST LIB PATH] [ICU LIB PATH]icuuc.lib
为您的机器提供相应的headers/libs路径
复制相应的boost dll到包含test.exe的目录(boost_regx -vc100-mt-gd-1_45.dll和boost_unit_test_framework-vc100-mt-gd-1_45.dll)
当test.exe从上面的步骤运行时,我得到:-
Running 2 test cases...
*** No errors detected
Detected memory leaks!
Dumping objects ->
{789} normal block at 0x00410E88, 28 bytes long.
Data: < 0N U > 00 00 00 00 30 4E CD 55 00 00 00 00 01 00 00 00
{788} normal block at 0x00416350, 14 bytes long.
Data: <icudt46l-coll > 69 63 75 64 74 34 36 6C 2D 63 6F 6C 6C 00
{787} normal block at 0x00415A58, 5 bytes long.
Data: <root > 72 6F 6F 74 00
...lots of other blocks removed for clarity ...
我猜icu实际上是这里的罪魁祸首,因为它的名字在第二个块的开始。
只是做第一个测试(即只是创建一个标准regex而不是u32_regex)没有检测到内存泄漏。
在测试中添加多个u32_regex并不会导致更多的内存泄漏。
我试图通过使用u_cleanup()调用清理icu缓存,按照icu文档参见icu初始化和终止部分。
然而,我不是很熟悉icu库(实际上我只是使用它,因为我们想要unicode感知regex支持),不能看到如何获得u_cleanup()调用来实际清理数据时icu是由boost regex dll加载。
重申一下问题似乎是:-
在可选的icu支持编译的dll中boost regex(我很确定这使用了一个静态链接到icu,但这里可能是错误的)
如果我链接到icucc。lib中的测试程序,以便我可以调用u_cleanup(),这似乎不会影响通过boost regex库加载的ICU实例所持有的内存(好吧,如果它确实会相当奇怪)
我在regex库中找不到任何调用,允许我要求它清理ICU数据,这是我们真正想要调用的地方。
u_cleanup
是清理数据的,但是如果有任何项仍然打开,它不能清理数据。
你可以尝试不调用任何boost函数,而只是调用u_cleanup(),看看是否有任何泄漏?然后尝试调用u_init()
和u_cleanup()
我不熟悉Boost,不知道上面的代码是否会清理正则表达式,或者Boost是否有任何内部缓存。泄露的对象看起来不像通常的ICU数据,如果ICU的数据仍然是开放的,你会看到相当多的数据,而不是14+5字节
既然我确实解决了这个问题(在boost用户的帮助下),我想我也可以在这里回答这个问题。
问题是在撕毁的顺序-如果在boost regex dll中的静态对象在单元测试框架之前没有被破坏,那么这仍然会缓存一些数据。因此,UTF报告内存泄漏。仅仅调用u_cleanup()是不够的。
确保顺序的最简单方法是将单元测试框架作为一个静态库链接起来——然后在任何dll之后销毁它的对象,因此不会将缓存的对象报告为内存泄漏,因为它们已经被销毁了。
- 将字符串存储在c++中的稳定内存中
- C++ 指针的内存地址和指向数组的内存地址如何相同?
- Win32编译器选项和内存分配
- 当vector是tje全局变量时,c++中vector的内存管理
- 带内存和隔离功能的SQLite
- 是否可以通过C++扩展强制多个python进程共享同一内存
- 迭代时从向量和内存中删除对象
- 在C++中打印指向不同基元数据类型的指针的内存地址
- 这个指针和内存代码打印是什么?我不知道是打印垃圾还是如何打印我需要的值
- 多个文件的内存分配错误"在抛出 'std :: bad_alloc' what (): std :: bad_alloc 的实例后终止调用" [C++]
- 为什么示例代码访问IUnknown中已删除的内存
- 如何在C++类内存结构中创建"spacer"?
- 从构造函数抛出异常时如何克服内存泄漏
- malloc() 可能出现内存泄漏
- 如何理解将半精度指针转换为无符号长指针和相关的内存对齐
- 在调用FreeLibrary后,释放动态链接到具有相同版本的CRT堆的DLL的内存
- 如何针对特定情况调试和修复此双自由内存损坏问题
- 类型总是使用其大小存储在内存中吗
- 有没有一种方法可以测量c++程序的运行时内存使用情况
- 使用regex.h时内存泄漏