朝倉 輝
akira_asaku****@fujim*****
2010年 7月 20日 (火) 15:57:16 JST
はじめまして。 朝倉といいます。 mecabのソースを追っているのですが、いくつかバグのようなコードが見受けら れますので、報告しておきます。 ×feature_index.cppのstrdupで'\0'が追加されないため、 メモリ確保時にクリアされていないとメモリ範囲外アクセスが生じます。 Windows環境でのデバッグ実行時にクラッシュしました。 リリース版でもトレーニング結果が異なりました。 const char *FeatureIndex:strdup(const char *p){ size_t len = std::strlen(p); char *q = char_freelist_.alloc(len+1); //std::strncpy(q, p, len);//len+1の間違い. std::strncpy(q, p, len); } ×dieクラスでのデストラクタでのexitはメモリリークの可能性があるので、 operator&関数内で呼ぶべきです。 class die { public: die() {} ~die() {} int operator&(std::ostream&) { std::cerr << std::endl; throw std::runtime_error("error occured");//exitの代わりに例外を投げて、 外側で catchするように修正するのもいいと思います。 } }; ×デストラクタでのlongjmpはメモリリークするので避けた方がよいと思われます。 これは、エラーメッセージを表示した際にリークしていきます。 なるべくマクロを使っているところを書き換えないでサンプルコードを書いて おきます。 struct dummy_close { void close(){} }; template<class S,class T> class wlog { S * self_; public: whatlog & what_; wlog( whatlog & what, S * self = 0 ) : what_( what ), self_( self ) { what_.stream_.clear(); } T operator&(std::ostream &) { if ( self_ ) self_->close(); return static_cast<T>( 0 ); } }; #define CHECK_WLOG(condition,self,type) if (condition) {} else return wlog<self,type>( what_ ) & what_.stream_ << __FILE__ << "(" << __LINE__ << ") [" << #condition << "] " #define CHECK_TYPE(condition,type) CHECK_WLOG(condition,MeCab::dummy_close,type) #define CHECK_CLOSE_FALSE(condition) CHECK_WLOG(condition,self_type,bool) #define CHECK_0(condition) CHECK_TYPE(condition, int) #define CHECK_FALSE(condition) CHECK_TYPE(condition, bool) #define CHECK_CHARPTR(condition) CHECK_TYPE(condition, char*) なお、self_typeはマクロを呼び出すクラスでtypedefを追加する必要があります。 ・createTaggerでDLL内でメモリを確保して外部でdeleteを呼ぶと、メモリが破 壊される可能性があります。 deleteTaggerなどの関数が必要です。 ・Taggerクラスに__declspec(dllexport)定義が抜けています。 但し、このクラスを使わなければ平気です。 ・ascii_to_ucs2で*mblen=1が抜けています。 但し、実行時にここは通らないと思われます。 ・setGlobalError,getGlobalError等での排他制御が不完全なので、 同時実行時に問題が生じる可能性が多少あります。