用boost::locale::conv转换字符编码时的坑!

这两天编写一个网络通讯程序的时候,遇到字符编码在GBK和UTF-8之间转换的问题,打算用boost::locale::conv里面的函数来转换。代码很简单,调用boost::locale::conv::between即可。在eclipse cdt中编码,用MinGW作为编译器,在家里的电脑上编译链接调试,一切OK!

第二天,在单位电脑上写了同样的代码,按照同样的方式设定了project属性,链接的时候却出错了,提示:

undefined reference to `libiconv_open'
undefined reference to `libiconv_close'
undefined reference to `libiconv'

看看project属性中关于链接库的设定,所需的libiconv.a库是在库的设定路径中的,看看CDT调用的链接命令如下:

g++ "-LD:\\devlib\\boost\\mingw\\lib" -o studyEncodeConvert.exe main.o -liconv -lboost_locale-mgw10-mt-sd-x64-1_75

说明也调用了iconv库。这就诡异了,明明所需的库都已经在链接命令里得到调用,怎么就还会出现“未定义的引用”这种错误呢?莫非是我编译的boost库有问题?

索性就重新编译了boost,用了各种build指令的组合,折腾了一整天,错误仍旧没有解决。抓狂了!!!丧气了!!!

胡思乱想之下,感觉会不会是CDT调用编译器时有问题?那么换个IDE看看。于是用Code::Blocks重新构造了project,指定了boost_locale-mgw10-mt-sd-x64-1_75,开始编译链接,结果出现前面的错误,看看project的设定,哦哦,忘记指定iconv库了。在project的链接库属性里把iconv加上,build。咦?竟然成功了!C::B里的设定跟CDT里的一样的,咋会成功的?得,仔细对照一下IDE调用编译器的命令行吧。C::B调用的命令行如下:

g++ -LD:\devlib\boost\mingw\lib -o studyEncodeConvert.exe main.o -lboost_locale-mgw10-mt-sd-x64-1_75 -liconv

看上去跟CDT的调用方式好像没啥区别?仅有的区别就是两个外部链接库的顺序不同。等等,顺序不同?难道是这个原因?那就把CDT里面的库的顺序调换一下吧。把boost_locale-mgw10-mt-sd-x64-1_75和iconv的顺序调整了一下,使得boost_locale-mgw10-mt-sd-x64-1_75在iconv之前。然后再编译,成了!!!敢情竟然是链接库的顺序会导致编译成功或者失败?再看看当时家里写得程序的project中指定的库的顺序,还真就是boost_locale-mgw10-mt-sd-x64-1_75在前,iconv在后,有照片为证。

这一点小小的设定就是我浪费了一整天时间来穷折腾boost的罪魁祸首!!!这真是太坑了!我一直以为gcc编译器在一个中间目标文件里找不到符号的时候会在所有参与编译的文件中查找,现在看来并非如此,gcc只会在当前被处理文件后面的文件中查找。

回想以前也偶尔出现过类似的问题,记得当时是重建了project之后就好了。现在看起来,应该是重建project的时候无意中改变了一些编译要素的顺序,误打误撞地弄成功了。现在总算弄明白了。赶紧记录下来。


版权声明:本文为kingfox原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。