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模式了
C++语言不直接处理输入输出,而是通过一族定义在标准库中的类型来处理IO。这些类型支持从设备读取数据、向设备写入数据的IO操作,设备可以是文件、控制台窗口等。还有一些类型允许内存IO,即从string读取数据,向string写入数据。
#include&lt;iostream&gt;
istream; wistream;
ostream; wostream;
iostre...
1. 使用ifstream读文件时被截断
ifstream file;
使用文本方式读时,即file.open(filePath, ifstream::in),如果碰到字符0x1A(SUB 换置)时就停止读,后面的内容就被截断了。
使用二进制读可以解决此问题,即 file.open(strFilePath.c_str(),
ifstream::in | std::ios::binary);
INT CWriteFileBase::OpenCsvFile(ofstream& of, const CString& strLogFile)
of.open(strLogFile, std::ofstream::app);
if (!of)
return RET_ERR;
return RET_OK;
如果已经of.open了没有关闭,再执行of.open会失
关键问题1:如果文件不存在,三种流如何处理? 关键问题2:文件中已有内容,对文件读写时如何控制从何处开始?
ps1: fstream头文件不包含有ifstream和ofstream,后者不是前者的子类
ps2: iostream头文件自动包含了istream和ostream,cin 是istream对象,cout是ostream对象
ps3: io流对象不可拷贝、赋值,fstream fs
ofstream奇怪问题解决方法
最近使用ofstream写数据到文件中出现了一些奇怪的问题,发现有时候写入的数据和原始数据不一致,经过观察发现,有些地方多了0D这个东西,查字符
表得知是回车符。因此得知可能是自动插入了回车换行。而且每个0D都在0A前面,这样更加表明ofstream确实会自动在0A前加入0D以表示win下
的回车换行。
解决方法就是使用二进制方式写入,默认是字节流...
c++随笔——linex下无法运行多线程问题
因为pthread 库不是 Linux 系统默认的库,运行时候可以进行连接多线程的外部库,正常编译后面加上 -lphread 就好拉
g++ a1.cpp -o a1 -lpthread
提供个小粒子,给大家实验。。。
#include <iostream>
#include <thread>
using namespace std;
void myprint()
cout << "我的线程开始" <
在这个示例中,我们使用 `std::ofstream` 类打开一个名为 `output.txt` 的输出文件流,并使用 `<<` 运算符将字符串 "Hello, world!" 写入文件中。注意,在写入完数据后,我们需要使用 `close()` 函数关闭文件流。这是为了确保所有数据都被写入文件并将其保存在磁盘上。最后,我们向控制台输出一条消息,表示数据已经成功写入文件。
需要注意的是,如果打开的文件不存在,则将创建该文件。如果文件已经存在,则会覆盖原有的文件内容。如果您想要在文件末尾添加新的数据而不是覆盖原有的内容,可以使用 `std::ofstream::app` 模式来打开文件流,例如:
```c++
std::ofstream output("output.txt", std::ios::app);
这将以追加模式打开文件流,从而在文件末尾添加新的数据而不是覆盖原有的内容。