tinyxml一直很好用,一直以源码方式添加到工程中使用。但如果在工程中使用了一个动态链接库(比如osgEarth)看,并且这个动态链接库也以源码方式使用了tinyxml,可能就不好玩了:编译或者运行时的错误莫名奇妙,让人抓瞎。

环境

osgEarth 2.7 / Qt 4.8.1/ 中标麒麟Linux

问题描述

做了一个基于osgEarth / OpenSceneGraph的场景演示程序, 基本功能已经完成差不多了,然后开始增加程序的xml配置功能。从一个之前的项目中拷贝了tinyxml源文件、以及AppConfig类(单体类,集合了所有程序配置参数,提供loadConfigFromFile、loadDefaults等接口,调用tinyxml相关函数实现xml解析),修改相关实现……做完之后编译、运行,程序居然直接崩溃了。然后排查了很久,发现竟然是因为osgDB::readNodeFile失败了。

这让我觉得有点莫名奇妙:这和tinyxml有啥关系???

既然问题是在工程中添加了tinyxml后出现的,直接的解决办法是使用除tinyxml的其它方式来实现xml解析功能。在OSG、osgEarth的源码里找了找,发现了osgEarth/XmlUtil,看名字估计是用来处理xml的。程序已经链接了libosgEarth,那么XmlUtil的相关函数应该也是可用的。于是修改工程,移除tinyxml,并使用XmlUtil提供接口实现AppConfig::loadConfigFromFile函数的功能。编译ok,但是运行发现配置文件没有被成功读取。尝试在osgEarth的源码中寻找XmlUtil使用的例子,居然一无所获!这也奇怪,一个没有被任何地方引用的类,要它干嘛?

然后又仔细看了看XmlUtil的实现函数,发现这货底层也是基于tinyxml的,原来osgEarth也是以源码方式使用了tinyxml。这让本文开头的错误看起来不是那么匪夷所思了:虽然不清楚确切原因,至少还是有些关联的。任何问题总有原因,没有“奇怪”的。

那么使用osgEarth源码中的tinyxml是否可行呢?测试了一下还是不行:仅包含tinyxml.h时,编译报错;添加tixmlstr.cpp到工程后,编译通过,但运行出现段异常;添加其他tixml*.cpp到工程后,又回到了osgDB::readNodeFile失败这一错误。

如果不想折腾,只能考虑用Qt自带的xml相关类了。