2011-07-29 22 views
3

在啓用了可選ICU支持的情況下使用boost regex類時(詳情請參見boost documentation),我似乎得到了內存泄漏或者某種內存緩存,我無法似乎重置/清理。在Win32上使用icu u32_regex內存泄漏/緩存提升

有沒有其他人看到這個,也許知道一種清除緩存的方式,以便增強單元測試框架不會報告內存泄漏?

我的問題的細節是: -

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) 

雖然我沒有嘗試這個具有提升1.42與ICU 4.2.1我碰巧已經建立了與我相同的結果,系統上,因此不認爲它的一個問題,將通過改變以提升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正則表達式DLL加載。

只是爲了重申這個問題似乎是: -

與可選的ICU支持編譯一個dll

升壓正則表達式(我敢肯定,這個使用靜態鏈接到重症監護病房,但可能是錯在這裏)

如果我在測試程序中鏈接到icuuc.lib,以便我可以調用u_cleanup(),這似乎不會影響ICU實例通過boost正則表達式庫加載的內存(如果它確實如此)

我找不到正則表達式庫中的任何調用,它允許我要求它清理ICU數據,它真的是我們想要的數據歡迎來電。

回答

1

u_cleanup是清理數據,但如果任何項目仍處於打開狀態,它無法清理數據。

你可以嘗試不調用任何boost函數,但只是調用u_cleanup()並查看是否有任何泄漏?然後嘗試只是打電話u_init()然後u_cleanup()

我不熟悉Boost知道上面的代碼是否會清除正則表達式,或者如果boost有任何內部緩存。泄漏的物體看起來不像通常的ICU數據,如果ICU的數據仍然打開,你會看到相當多的數據,而不是14 + 5字節。

+0

謝謝 - 這只是泄露數據的開始 - 我已經編輯了希望更清晰的問題。 –

+0

進一步調查表明,icu實際上是動態鏈接而不是靜態鏈接。 Boost正則表達式似乎優雅地退化,如果沒有找到icu dll,這就是爲什麼刪除icu dll不會生成dll找不到消息(這是我的簡單測試,看看動態或靜態鏈接)。因此,u_cleanup()應該可以工作(我認爲) –

+1

如果您構建的ICU的預處理器標誌UCLN_NO_AUTO_CLEANUP定義爲0(您可以在uconfig.h的頂部添加一個#define),那麼ICU將在卸載DLL時清除自身。如果ICU已被清理或永不加載,則u_cleanup可以安全調用。 –

1

只是覺得我可以在這裏回答這個問題,因爲我做了解決這個問題(在助推用戶的幫助下)。

問題是按照拆卸的順序 - 如果boost regex dll中的靜態對象沒有在單元測試框架之前被破壞,那麼這仍然會緩存一些數據。所以UTF會報告內存泄漏。簡單地調用u_cleanup()是不夠的。

確保順序最簡單的方法是將單元測試框架作爲一個靜態庫鏈接 - 然後在任何dll之後獲取它的對象破壞,因此不會將緩存的對象報告爲內存泄漏,因爲它們已經存在自毀。