必须检查 loadfile() 返回值,非 tixml2_success 时调用 geterrorstr1()/geterrorstr2() 定位错误;操作节点前需判空;savefile() 需手动加 utf-8 bom;多线程须隔离 xmldocument 实例。

tinyxml2::XMLDocument::LoadFile() 失败但没报错?检查返回值和 GetErrorStr1()
很多人调用 LoadFile() 后直接用 FirstChildElement(),结果段错误或返回空指针——其实加载根本没成功,只是没检查返回值。TinyXML2 不抛异常,所有错误都靠返回码和内部状态体现。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 必须检查
LoadFile()返回的tinyxml2::XMLError,非TIXML2_SUCCESS就别往下走了 - 加载失败时,立刻打印
doc.GetErrorStr1()和doc.GetErrorStr2(),它们分别对应错误位置的上下文行和列,比“failed to parse”有用十倍 - 路径含中文或空格?确保传入的是 UTF-8 编码的
const char*,Windows 下用_setmode(_fileno(stdout), _O_U16TEXT)无用,得自己转码再传给LoadFile()
读取节点内容时 FirstChildElement("xxx")->GetText() 崩溃?先判空再取值
XML 节点不存在、文本为空、被注释包裹……这些都会让 FirstChildElement() 返回 nullptr,接着调 GetText() 必然 crash。这不是 bug,是设计如此:TinyXML2 把“查找失败”和“值为空”严格区分开。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 永远把
FirstChildElement()结果赋给临时指针,判断是否为nullptr再操作 -
GetText()返回的是const char*,可能为nullptr(比如节点只有子元素、无文本),要二次判空 - 需要默认值?别写
elem->GetText() ?: "default",C++ 里?:对nullptr不安全,改用三目运算符显式判断
修改 XML 后保存乱码?SaveFile() 默认不写 BOM,UTF-8 中文需手动处理
在 Windows 记事本里打开保存后的 XML 显示乱码,大概率是因为 TinyXML2 输出纯 UTF-8 无 BOM,而记事本默认按 ANSI 解析。VS Code 或 Notepad++ 能正常识别,但业务系统若依赖记事本查看就容易出问题。
本文档主要讲述的是使用JSON进行网络数据交换传输;JSON(JavaScript ObjectNotation)是一种轻量级的数据交换格式,易于阅读和编写,同时也易于机器解析和生成,非常适合于服务器与客户端的交互。JSON采用与编程语言无关的文本格式,但是也使用了类C语言的习惯,这些特性使JSON成为理想的数据交换格式。 和 XML 一样,JSON 也是基于纯文本的数据格式。由于 JSON 天生是为 JavaScript 准备的,因此,JSON的数据格式非常简单,您可以用 JSON 传输一个简单的 St
实操建议:
立即学习“C++免费学习笔记(深入)”;
-
SaveFile()本身不提供编码参数,它只输出 UTF-8 字节流,BOM 得自己加 - 保存前用
doc.SaveFile("out.xml", true)的第二个参数启用格式化(缩进),但不影响编码 - 真要加 BOM:打开文件用二进制模式,先写入
0xEF, 0xBB, 0xBF三个字节,再调doc.SaveFile()到同一文件句柄(需重写XMLPrinter或绕过 API)
多线程下共享 XMLDocument 实例?别这么做,每个线程用独立实例
XMLDocument 内部有缓存、字符串池和节点链表,不是线程安全的。即使只读,多个线程同时调 FirstChildElement() 也可能因内部迭代器冲突导致崩溃——尤其在频繁解析小 XML 的服务中容易复现。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 每个线程解析自己的 XML,用栈上
XMLDocument doc最省心 - 如果必须复用(比如配置只读一次),用
std::shared_ptr+std::mutex保护整个解析过程,而不是保护单个方法调用 - 注意
XMLNode指针不能跨XMLDocument实例使用,复制节点要用DeepClone(),否则释放源文档后指针悬空
最常被忽略的一点:TinyXML2 的内存模型是“文档拥有全部节点”,DeleteChild() 后节点内存立即释放,没有引用计数。一旦你把某个 XMLElement* 存到容器里又删了父节点,后续访问就是野指针——这种 bug 很难用 ASan 捕获,因为释放后内存可能还没被覆写。









