当使用boost regex类并启用了可选的ICU支持时(详情请参阅boost documentation)我似乎得到了内存泄漏或者某种内存缓存,我似乎无法重置/清理。
有没有其他人看过这个并且可能知道清除缓存的方法,以便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)
虽然我尝试使用带有icu 4.2.1的增强1.42,我碰巧在我的系统上构建了相同的结果,所以不要认为它是一个可以通过改为升级来解决的问题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
使用适合您机器的标头/库的路径
将相应的boost dll复制到包含test.exe的目录(如果它们没有进行修改)(boost_regex-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实际上是罪魁祸首,因为它在第二个区块的开头有它的名字。
只进行第一次测试(即仅创建标准正则表达式而不是u32_regex)没有检测到内存泄漏。
在测试中添加多个u32_regex不会导致更多内存泄露。
我尝试按照icu documentation使用u_cleanup()调用来清理icu缓存,请参阅ICU初始化和终止部分。
但是我对icu库不太熟悉(实际上我只是使用它因为我们需要unicode感知正则表达式支持)并且无法看到如何在ICU正在进行u_cleanup()调用时实际清理数据由boost regex dll加载。
重申问题似乎是: -
在使用可选的icu支持编译的dll中提升正则表达式(我很确定它使用静态链接到icu但在这里可能是错误的)
如果我链接到测试程序中的icuuc.lib以便我可以调用u_cleanup(),这似乎不会影响通过boost正则表达式库加载的ICU实例所拥有的内存(如果这样,那将是相当奇怪的它确实)
我在regex库中找不到任何调用,它允许我要求它清理我们想要拨打电话的ICU数据。
答案 0 :(得分:1)
u_cleanup
可以清理数据,但是如果任何项目仍处于打开状态,则无法清理数据。
你可以尝试不调用任何boost函数,只是调用u_cleanup()并查看是否有任何泄漏?然后尝试只调用u_init()
然后调用u_cleanup()
我不熟悉Boost知道上面的代码是否会清理正则表达式,或者boost是否有任何内部缓存。泄露的物体看起来不像通常的ICU数据,如果ICU的数据仍然打开,你会看到相当多的数据,而不是14 + 5字节
答案 1 :(得分:1)
以为我可以在这里回答这个问题,因为我解决了这个问题(在推特用户的帮助下)。
问题在于拆除的顺序 - 如果在单元测试框架之前没有破坏boost regex dll中的静态对象,那么这仍然会缓存一些数据。所以UTF报告内存泄漏。简单地调用u_cleanup()是不够的。
确保顺序的最简单方法是将单元测试框架作为静态库链接 - 然后在任何dll之后使其对象被破坏,因此不会将缓存的对象报告为内存泄漏,因为它们已经被破坏