LPC1768配合KEIL IDE将字符数组转为XML传输时数据异常如何解决
问题原因及修复方案
核心错误点
- XML语法合法性问题:原始char数组属于二进制数据,直接嵌入XML文本节点会存在两个致命问题:
- 若数据包含XML预留特殊字符(
<、>、&、"、'),会直接破坏XML标签结构,导致客户端解析失败 - 若数据包含
0x00(ASCII空字符),会被C语言识别为字符串结束符,直接截断后续内容,导致发送的数据不完整
- 若数据包含XML预留特殊字符(
- 字符串拼接逻辑缺陷:
- 每次调用
strcat都需要从头遍历目标字符串找到结束符,20000次循环的时间复杂度为O(n²),LPC1768的性能不足以支撑该操作,容易出现运行超时、数据写入异常 - 未做缓冲区边界检查,极容易出现栈溢出,导致内存数据被篡改
- 若
str_temp未初始化为空字符串,首次strcat就会向非法内存地址写入数据
- 每次调用
- 二进制数据存储方式错误:XML的文本节点不支持直接存储不可打印的二进制字符,即使没有特殊字符,也容易出现编码不兼容导致的数据异常。
修复方案
- 二进制数据转码:将20000字节的原始char数组先做Base64编码,转换为纯可打印ASCII字符串后再嵌入XML的
<value>节点,彻底避免特殊字符、空字符的问题 - 替换字符串拼接逻辑:放弃
strcat循环拼接,直接使用指针偏移或者单次snprintf完成整段XML的组装,同时强制做缓冲区边界检查 - 预留足够缓冲区空间:Base64编码后的数据长度为原始长度的4/3(向上取整),加上XML固定标签的长度,提前分配足够大的发送缓冲区。
修复后的示例代码
// 假设已经引入Base64编码函数,输出长度计算公式:((in_len + 2) / 3) * 4 #define RAW_DATA_LEN 20000 #define BASE64_BUF_LEN ((RAW_DATA_LEN + 2)/3)*4 #define XML_FIXED_LEN 100 // XML固定标签的总长度 #define SEND_BUF_LEN (BASE64_BUF_LEN + XML_FIXED_LEN + 1) // 多留1字节存结束符 char send_buf[SEND_BUF_LEN] = {0}; char base64_buf[BASE64_BUF_LEN] = {0}; int fill_loop; // 1. 先读取全部原始数据到临时缓冲区 unsigned char raw_buf[RAW_DATA_LEN]; for(fill_loop=0; fill_loop<RAW_DATA_LEN; ++fill_loop) { raw_buf[fill_loop] = (unsigned char)Spi_Flash_read_byte(fill_loop + 300); } // 2. 原始二进制转Base64 base64_encode(raw_buf, RAW_DATA_LEN, base64_buf, BASE64_BUF_LEN); // 3. 一次性组装完整XML snprintf(send_buf, SEND_BUF_LEN, "<form>\n" "<text>\n" "<id>parameters</id>\n" "<value>%s</value>\n" "</text>\n" "</form>", base64_buf); // 后续直接发送send_buf即可
补充说明:如果业务要求不能用Base64编码,必须存储原始字符的话,需要额外加XML特殊字符转义逻辑,在写入
<value>节点前逐个替换特殊字符为对应的XML实体,同时要保证原始数据不包含0x00空字符。
内容的提问来源于stack exchange,提问作者Milad Rasouli
相关产品推荐
相关产品推荐

