CRF 移植

Part 1.

前些天把词性标注的接口与分词的接口全并在一起,终于达到了足够稳定的程度(小数据量自己测试)。为在线上作为服务提供之用,而必须改装为线程安全的版本,就编程习惯而言问题不大:1.将strtok 的使用换成strtok_r ;2. 非线程间共享的全局变量封类进终端管理类,而全局共享的依然可以写成全局变量的形式,比如配置文件类CConfig config("res.config")。但其中的线程池的管理类就较麻烦了,设计考虑较多。为了之后的扩展和速度可能存在的问题,将其设计成终端用户 一个用户拥有一个线程池的方式,而不是所有的用户共用一个线程池,当然也可以设计成这样,不过因为用户之间是不相关的,而且这样的设计并不复杂,所以暂时采用一个用户拥有一个线程栈吧。

这其中到是学了一招,以前一直没用过:一个类的static函数怎样访问该类的非static变量?

方式有多种,不过核心都是在调用这个static函数时传入this指针,在函数体之初将这个void*的参数转化为这个类的对象

[CMyClass* myObj = (CMyClass*) arg;]
在操作非static变量时加上this->就可以了。

这个多用在pthread_create这个函数中。

参见:http://hi.baidu.com/ivy_jing/blog/item/abe56f123ecab414213f2e1c.html


Part 2.

线程安全版调通之后就是移植问题了。

由于CRF++本身的Makefile实在是复杂,之间也是直接修改其内部代码(因为要优化、提速、查询解码等),将其自成的libcrfpp.a作为本服务器上的静态调用没有问题,但是移植到其它服务器就不行了,先是剔除thrift等相关内容后,将其项目中的库文件主动打包

ar -rc libcrfpp.a *.o .libs/*.o libs/*.a libs/*.so

并将其libcrfpp.so.0也同时提供,而且要将*.so.0的所在目录放在环境变量里(加在 ld.so.conf 中,并使其生效(idconfig),  有一段时间忘记生效了,搞死人了,之前是真不知道要这样,还是同事帮忙才知道的 )。


Part 3.

移植成功之后,还利用了Valgrind 进行了内存查看,解决了每个用例3个字节的泄漏问题,这个比较赞,之前都没发现。以后要常用Valgrind这个工具。


总结:

真是不移植不知道问题的存在,不给别人提供服务不担心自已代码的隐患。

以后写代码要从一开始就注意线程安全性,并常用Valgrind这样的工具,对库的封装和使用也要注意。

;