尝试将数字写入二进制文件时引发异常
Posted
技术标签:
【中文标题】尝试将数字写入二进制文件时引发异常【英文标题】:Exception is thrown when trying to write a number to a binary file 【发布时间】:2018-10-04 15:26:08 【问题描述】:我一直在尝试用 C++ 创建自己的二进制文件。我正在做的是我定义了一个结构,它实际上与 dds 标头的结构相同。所以我要做的是首先向二进制文件写入一个小版本号,以查看我处于哪个阶段,然后我将整个结构写入文件,最后我将一个简单的文本字符串写入文件。 但是,当我尝试将版本号写入文件时,会引发如下异常:“TestApplication7.exe 中在 0x0F377236 (msvcp140d.dll) 处引发异常:0xC0000005:访问冲突读取位置 0x499602DB。”
所以基本上我所做的是在我的 cpp 文件顶部定义一个版本号,如下所示:
#define VERSION_NR 0x499602DB
然后我只是想把这个数字写入二进制文件。
这是我的示例代码:
void MyFile::Save(std::string ddsPath, MyFile::FileHeader header, const std::string texturePath)
header.PathLen = texturePath.length();
const char* bufferreinterpret_cast<const char*>(&texturePath);
const char* versionreinterpret_cast<const char*>(VERSION_NR);
std::ofstream output(ddsPath, std::ios::binary);
output.write(version, sizeof(VERSION_NR)); //Here is where the exception is thrown
ext->WriteStruct(output, header); //Writing the hole header to the file
output << texturePath; //Outputting a simple text to the file
原来是这样的代码:
output.write(version, sizeof(VERSION_NR));
这导致异常被抛出,我不知道我做错了什么,因为我对 c++ 编程非常陌生。我确实尝试在“保存”方法中创建一个 const DWORD 而不是使用宏,但我仍然遇到相同的异常。 我不知道这是否有帮助,除了“访问冲突读取位置 0x499602DB”的消息与我的宏的值相同的“位置”。
如果有人可以帮助我,或者只是指出我正确的方向,我将不胜感激。 谢谢!
【问题讨论】:
首先摆脱那些reinterpret_cast
s。对于初学者来说,规则是reinterpret_cast
总是错误的。
显示的代码似乎试图将reinterpret_cast
指向std::string
的指针转换为const char *
。那是... 不起作用。这是对 C++ 工作原理以及 C++ 对象的全部含义的根本误解。
@PeteBecker a reinterpret_cast
或 c 样式转换在将数字写入二进制 std::ostream
时很难避免
@SamVarshavchik 是的,那行代码只是我在弄清楚这一切如何工作时所做的事情,我没有在方法中的任何地方使用它,所以它只是我忘记的一些剩菜删除。感谢您指出!
@AlanBirtles -- reinterpret_cast
在这里很容易避免。 static_cast<const char*>(static_cast<void*>(&whatever))
。并且这种强制转换组合不会将整数值转换为指针。
【参考方案1】:
如果我们去掉宏和许多其他不相关的代码,我们会得到:
int version = 0x499602DB;
const char* ch = reinterpret_cast<const char*>(version);
std::ofstream output("out.bin", std::ios::binary);
output.write(ch, sizeof(version));
您是正确的,您的版本值出现在错误消息中这一事实是一个线索。第二行将整数值转换为地址为0x499602DB
的字符指针。由于当output.write
尝试访问该地址时,该地址未指向有效的内存地址,因此操作系统不允许该操作并引发访问冲突。
正确的代码是:
int version = 0x499602DB;
const char* ch = reinterpret_cast<const char*>(&version);
std::ofstream output("out.bin", std::ios::binary);
output.write(ch, sizeof(version));
或者如果你想写一个字符串,就避免一起转换:
const char version[4] = '\xDB','\x02','\x96','\x49';
std::ofstream output("out.bin", std::ios::binary);
output.write(version, sizeof(version));
另请注意,一旦我们修复了此崩溃,以下内容也是不正确的:
const char* bufferreinterpret_cast<const char*>(&texturePath);
而且应该是:
const char* buffer = texturePath.c_str();
texturePath
是一个std::string
对象,指向它的指针不能转换为char*
,c_str()
方法返回一个const char*
指针,然后您可以将其传递给std::ofstream::write
,或者只使用@987654334 @ 就像你已经在做的那样,只需删除 buffer
变量。
【讨论】:
【参考方案2】:VERSION_NR 不是变量,因此 char* 指向随机内存。 不要使用宏,创建一个变量,获取一个指针,就像你对其他数据所做的那样。
【讨论】:
以上是关于尝试将数字写入二进制文件时引发异常的主要内容,如果未能解决你的问题,请参考以下文章
每当我尝试将数字数据写入我的 .txt 文件时,它都会引发错误
尝试使用 FileLock、Python 写入文件时权限被拒绝