C++ 在Win32上使用icu u32_regex内存泄漏/缓存进行增强
当在启用可选ICU支持的情况下使用boost regex类时(有关详细信息,请参阅),我似乎遇到了内存泄漏,或者更确切地说是发生了某种无法重置/清理的内存缓存 是否有其他人看到了这一点,并且可能知道一种清除缓存的方法,以便boost单元测试框架不会报告内存泄漏 我的问题的详细信息如下:-C++ 在Win32上使用icu u32_regex内存泄漏/缓存进行增强,c++,dll,icu,boost-regex,C++,Dll,Icu,Boost Regex,当在启用可选ICU支持的情况下使用boost regex类时(有关详细信息,请参阅),我似乎遇到了内存泄漏,或者更确切地说是发生了某种无法重置/清理的内存缓存 是否有其他人看到了这一点,并且可能知道一种清除缓存的方法,以便boost单元测试框架不会报告内存泄漏 我的问题的详细信息如下:- ICU version 4.6.0 (Built using supplied vs2010 solution in debug and release configuration) Boost version
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)
虽然我在ICU4.2.1上使用boost 1.42进行了尝试,但我碰巧在我的系统上构建了该系统,并获得了相同的结果,所以不要认为这是一个问题,可以通过更改为最新版本的boost 1.47 ICU4.8.1来解决
编译以下代码(Test.cpp):-
具有适用于您的计算机的标题/库的适当路径
将适当的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 ...
运行2个测试用例。。。
***未检测到错误
检测到内存泄漏!
转储对象->
0x00410E88处的{789}正常块,28字节长。
数据:<0N U>00 00 00 30 4E CD 55 00 00 01 00 00
0x00416350处的{788}正常块,14字节长。
资料:69 63 75 64 74 34 36 6C 2D 63 6F 6C 6C 00
0x00415A58处的{787}正常块,5字节长。
资料:72 6F 6F 74 00
…为了清晰起见,删除了许多其他块。。。
我猜icu实际上是罪魁祸首,因为它的名字在第二个街区的开头
仅进行第一次测试(即仅创建标准正则表达式而不是u32_正则表达式)未检测到内存泄漏
向测试中添加多个u32_regex不会导致更多内存泄漏
我试图通过使用u_cleanup()调用来清理icu缓存,请参见icu初始化和终止部分
但是,我对icu库不太熟悉(实际上我只是使用它,因为我们需要unicode感知的正则表达式支持),并且不知道如何在boost正则表达式dll加载icu时调用u_cleanup()来实际清理数据
只是重申一下,问题似乎是:-
boost regex在一个使用可选icu支持编译的dll中(我很确定这使用了一个到icu的静态链接,但在这里可能是错误的)
如果我在测试程序中链接到icuuc.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之后,它的对象都会被破坏,因此不会将缓存对象报告为内存泄漏,因为它们已经被破坏。谢谢-这只是泄漏数据的开始-我编辑了这个问题,希望进一步的调查表明,icu实际上是动态连接的,而不是静态连接的。如果未找到icu dll,Boost正则表达式似乎会正常降级,这就是为什么删除icu dll不会生成dll未找到消息的原因(这是我查看动态链接还是静态链接的简单测试)。因此u#u cleanup()应该可以工作(我认为),如果在构建ICU时将预处理器标志UCLN_NO_AUTO_cleanup定义为0(可以在uconfig.h的顶部添加一个#define),那么ICU将在卸载DLL时自行清理。如果ICU已清理或从未加载,则可以安全调用u_cleanup。
C:\>cl test.cpp /I[BOOST HEADERS PATH] /I[ICU HEADERS] /EHsc /MDd -link /LIBPATH:[BOOST LIB PATH] [ICU LIB PATH]icuuc.lib
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 ...