Reputation: 172
I have been trying to create my own binary files in c++. What I am doing is that I have defined a structure that really is just the same structure of a dds header. So what I am trying to do is to first write a little version number to the binary file just to see at what stage I am in, then I write the whole structure to the file and last I write a simple textstring to the file. However when I am trying to write the version number to the file a exception like this is thrown: "Exception thrown at 0x0F377236 (msvcp140d.dll) in TestApplication7.exe: 0xC0000005: Access violation reading location 0x499602DB."
So basically what I am doing is that I am defining a version number at the top of my cpp file like this:
#define VERSION_NR 0x499602DB
and then I am just simply trying to write this number to the binary file.
Here is the code of my example:
void MyFile::Save(std::string ddsPath, MyFile::FileHeader header, const std::string texturePath) {
header.PathLen = texturePath.length();
const char* buffer{reinterpret_cast<const char*>(&texturePath)};
const char* version{reinterpret_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
}
So it is this code:
output.write(version, sizeof(VERSION_NR));
That is causing the exception to be thrown and I havce no idea what I am doing wrong since i am very new to c++ programming. I did try to create a const DWORD in the "Save" method instead of using a macro but I still got the same exception. I don't know if this helps or anything but the message "Access violation reading location 0x499602DB" is the same "location" as the value of my macro.
If someone could help me or maybe just point me to the right direction I would appreciate it. Thanks!
Upvotes: 0
Views: 179
Reputation: 36614
If we get rid of the macro and lots of other irrelevant code we get:
int version = 0x499602DB;
const char* ch = reinterpret_cast<const char*>(version);
std::ofstream output("out.bin", std::ios::binary);
output.write(ch, sizeof(version));
You are correct that the fact that the value of your version appears in the error message is a clue. The second line converts the integer value into a character pointer with the address 0x499602DB
. As this address doesn't point to a valid memory address when output.write
tries to access it the the OS doesn't allow the operation and raises and access violation.
The correct code is:
int version = 0x499602DB;
const char* ch = reinterpret_cast<const char*>(&version);
std::ofstream output("out.bin", std::ios::binary);
output.write(ch, sizeof(version));
Or as you are wanting to write a string anyway just avoid the cast all together:
const char version[4] = {'\xDB','\x02','\x96','\x49'};
std::ofstream output("out.bin", std::ios::binary);
output.write(version, sizeof(version));
Also note that once we've fixed this crash the following is also incorrect:
const char* buffer{reinterpret_cast<const char*>(&texturePath)};
And should simply be:
const char* buffer = texturePath.c_str();
texturePath
is a std::string
object a pointer to it is not convertible to char*
, the c_str()
method returns a const char*
pointer which you can then pass to std::ofstream::write
, alternatively just use output << texturePath
as you are doing already and just delete the buffer
variable.
Upvotes: 2
Reputation: 22043
VERSION_NR is not a variable, so the char* is pointing to random memory. Don't use macros, create a variable, get a pointer on it, as you did for the other data.
Upvotes: 1