ue4环境下,项目需要下载热更文件到本地,但是怪事出现了,编辑器PIE中运行良好的代码,打包后稳定崩溃。 经检查dmp文件,崩溃发生在输出流ofstream的close函数中。
TArray<uint8> saveData = 服务器http响应的body;
std::ofstream* file = new std::ofstream("文件名");
file << (const char*)saveData.getData();
file.close();
提前说下,ue4的TArray类似于std::vector,uint8 即 unsigned char
观察写入的文件发现,文件末尾会意外的出现随机字符。 VS的调试器无法解析saveData信息,显示为无效的字符串 在同事的不懈努力(各种写入方法穷举尝试) 发现将<<运算符替换为file.write() 方法后即可修复崩溃问题。 通过打印日志后发现
Log(saveData.Num(),strlen((const char*)saveData.getData()));
确认异常为strlen()引发,观察对内存数据发现, saveData[saveData.Num() - 1] == ‘m’ 众所周知,strlen的经典实现方式(未进行任何优化)
size_t strlen(const char* str)
{
size_t size = 0;
while(*(str + size) != '\0')
{
++size;
}
return size;
}
默认是以’\0’为字符串的结束标志,若该字符串中不包含这个结束符,则返回的值可能会远大于实际字符串长度,当流写入时,导致数组访问越界,最终导致崩溃。
解决方案很简单
file.write((const char*)saveData.getData(),saveData.Num());
file.close();
saveData.Add('\0');
file << (const char*)saveData.getData();
file.close();
显然第一种方案更好,避免了动态数据的空间增长的可能。 至于PIE模式下为什么不会崩溃,这就可能要问msvc的Debug模式了
|