uni-app App模式下,字符串首字节为0x00时,造成日志输出宕住
uni-app App模式下,字符串首字节为0x00时,造成日志输出宕住
| 开发环境 | 版本号 | 项目创建方式 |
|---|---|---|
| Mac | 14.2.1 | HBuilderX |
| iOS | iOS 14 | |
产品分类:uniapp/App
PC开发环境操作系统:Mac
HBuilderX类型:正式
HBuilderX版本号:3.96
手机系统:iOS
手机系统版本号:iOS 14
手机厂商:苹果
手机机型:iPhone6
页面类型:vue
vue版本:vue2
打包方式:云端
操作步骤:
let str = '\x00\x01\x03';
console.log('字符串是', str);
console.log('字符串是' + str);
预期结果:
输出日志
实际结果:
程序hang住
bug描述: 此BUG和具体App无关,预测是console.log日志族在输出ascii string时,存在BUG。
如下面的代码,在string的第一个字节为0x00时,程序不提示异常,进入到等待状态,后续代码不执行。 或者也可以用 let str = ‘\x00\x01\x03’;这种方式,用console.log进行日志输出,可重现。
try {
let str = '';
console.log('1.str is:', str);
str = 0x00;
console.log('2.str with value 0x00 is:', str);
str = '\0';
console.log('3.str with value slash zero is:' + str);
} catch (e) {
console.warn("字符串的日志输出错误", e)
}
更多关于uni-app App模式下,字符串首字节为0x00时,造成日志输出宕住的实战教程也可以访问 https://www.itying.com/category-93-b0.html
目前只有iOS的App模式下存在此问题,同样的代码,在Android的App模式,以及微信和支付宝小程序的Android及iOS均无问题。
更多关于uni-app App模式下,字符串首字节为0x00时,造成日志输出宕住的实战教程也可以访问 https://www.itying.com/category-93-b0.html
非printable的字符串日志输出,这个我们可以屏蔽掉,但是问题的起因在于我们需要向蓝牙下发数据,一个设备的pdu的第一个字节定义必须是0x00,所以发现了这个问题。
屏蔽了日志,我们的程序在iOS的App模式下也是不行,怀疑在处理0x00开始的string,其它地方也存在同样的BUG
在 uni-app 的 App 模式下,如果字符串的首字节为 0x00(即空字符 \0),可能会导致日志输出时出现异常,甚至导致应用“宕住”(即卡住或崩溃)。这是因为 0x00 在 C/C++ 等底层语言中通常被视为字符串的结束符,而在某些情况下,日志输出函数可能会错误地将其解释为字符串的结束,从而导致未定义的行为。
解决方案
-
检查字符串内容
在处理字符串之前,先检查字符串的内容,确保它不包含0x00这样的特殊字符。可以通过遍历字符串来检查每个字符的值。function containsNullByte(str) { return str.indexOf('\0') !== -1; } if (containsNullByte(myString)) { console.error("String contains null byte!"); } -
替换或移除空字符
如果字符串中包含0x00,可以将其替换为其他字符或直接移除。function removeNullBytes(str) { return str.replace(/\0/g, ''); } myString = removeNullBytes(myString); -
使用 Base64 编码
如果字符串中包含不可打印的字符(如0x00),可以将其转换为 Base64 编码后再进行日志输出。function encodeBase64(str) { return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, (match, p1) => { return String.fromCharCode('0x' + p1); })); } console.log(encodeBase64(myString)); -
使用 ArrayBuffer 或 TypedArray
如果你需要处理二进制数据,可以使用ArrayBuffer或TypedArray来存储和操作数据,而不是直接使用字符串。let buffer = new ArrayBuffer(10); let view = new Uint8Array(buffer); // 填充数据 view[0] = 0x00; view[1] = 0x01; // 日志输出时,可以将 ArrayBuffer 转换为十六进制字符串 function bufferToHex(buffer) { return Array.prototype.map.call(new Uint8Array(buffer), x => ('00' + x.toString(16)).slice(-2)).join(''); } console.log(bufferToHex(buffer)); -
调试和日志输出
在调试时,可以使用JSON.stringify将对象转换为字符串,这样可以避免直接输出包含特殊字符的字符串。console.log(JSON.stringify(myObject));

