3

オプションの ICU サポートを有効にしてブースト正規表現クラスを使用すると (詳細についてはブーストのドキュメントを参照)、メモリ リークが発生したり、リセット/クリーンアップできないメモリのキャッシュが発生したりするようです。

ブーストユニットテストフレームワークがメモリリークを報告しないように、キャッシュをクリアする方法を知っている人はいますか?

私の問題の詳細は次のとおりです:-

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

マシンのヘッダー/ライブラリへの適切なパス

適切なブースト 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 番目のブロックの先頭に名前があるため、icu が実際にここで犯人であると推測しています。

最初のテスト (つまり、u32_regex ではなく標準の正規表現を作成するだけ) を実行しただけでは、メモリ リークは検出されませんでした。

複数の u32_regex をテストに追加しても、メモリ リークが増えることはありません。

icu のドキュメントに従って、u_cleanup() 呼び出しを使用して icu キャッシュをクリーンアップしようとしました。ICU の初期化と終了のセクションを参照してください。

しかし、私は icu ライブラリにあまり詳しくありません (実際には、Unicode 対応の正規表現サポートが必要だったので使用しているだけです)。正規表現 dll をブーストします。

繰り返しますが、問題は次のように見えます:-

オプションの icu サポートを使用してコンパイルされた dll で正規表現をブーストします (これは icu への静的リンクを使用していると確信していますが、ここでは間違っている可能性があります)。

u_cleanup() を呼び出すことができるようにテスト プログラムで icuuc.lib にリンクすると、boost regex ライブラリを介してロードされた ICU のインスタンスが保持するメモリに影響を与えないように見えます (そうであればかなり奇妙です)。

正規表現ライブラリに呼び出しが見つかりません。これにより、実際に呼び出しを行う場所である ICU データをクリーンアップするように要求できます。

4

2 に答える 2

1

u_cleanupこれがデータをクリーンアップしますが、まだ開いているアイテムがある場合はデータをクリーンアップできません。

ブースト関数を呼び出さずに、u_cleanup()を呼び出して、リークがないかどうかを確認できますか?u_init()そして、電話してみてくださいu_cleanup()

上記のコードが正規表現をクリーンアップするかどうか、またはBoostに内部キャッシュがあるかどうかを知るためにBoostに精通していません。リークされたオブジェクトは通常のICUデータのようには見えません。ICUのデータがまだ開いている場合は、14 + 5バイトではなく、かなりの量のデータが表示されます。

于 2011-07-29T01:46:35.467 に答える
1

(ブーストユーザーの助けを借りて)これを解決したので、ここで質問に答えたほうがよいと思いました。

問題はティア ダウンの順序にあります - ユニット テスト フレームワークの前にブースト正規表現 dll の静的オブジェクトが破棄されない場合、これはまだ一部のデータをキャッシュしています。そのため、UTF はメモリ リークを報告します。u_cleanup() を呼び出すだけでは十分ではありません。

順序を確認する最も簡単な方法は、単体テスト フレームワークを静的ライブラリとしてリンクすることです。これにより、DLL の後にオブジェクトが破棄され、キャッシュされたオブジェクトは既に破棄されているため、メモリ リークとして報告されません。

于 2011-08-12T12:54:12.207 に答える