Sign in to follow this  
JoeMagoe

[C++] Reading and Writing an STL vector with fstream

Recommended Posts

I have a game that reads in a tile map through the fstream class. Recently, I learned about binary files, and I tried to convert my tilemap format. After a few changes, I slightly succeeded. I could save an SDL_Rect successfully, but there seemed to be problems with my vector for the tile map. It saved and read, seemingly correctly, but happened to fail afterwards. When I tried to access any instance from the vector, I was given a segmentation fault. After a TON of Googling, I found nothing. Just to see if it was a compatibility problem between fstream and vector or something, I loaded and saved the tile map as an array and then later converted to a vector for use. Turns out, the array makes it work perfectly. I have no idea why. Is there something I should know about concerning vectors and fstreams, and/or is there some special way to read and write vectors?

Share this post


Link to post
Share on other sites
I'm still VERY new to C++ (I just finished the summer course last Thursday), so I'm not sure if the solution I'm about to propose is accurate or not =)
Regardless, here we go...

Are you trying to access the vector through a pointer?

When vectors are re-sized dynamically (using push_back() for instance), the "newly sized" vector is moved to a completely different location in memory. Assuming that your vector has not been declared with a "pre set" size (or assuming that you're exceeding this size), it will be dynamically re-sized when it is updated with data from your fstream.

So, if you're trying to access the vector through a pointer, the pointer is pointing to the ORIGINAL memory location of the vector, NOT the new location where the vector actually resides.

The reason an array works is because they are static in their size and memory locations. You cannot dynamically re-size an array, therefore, if will always remain at the same location in memory, and any pointer pointing at the array will work.

Share this post


Link to post
Share on other sites
Quote:
Original post by tycse
I'm still VERY new to C++ (I just finished the summer course last Thursday), so I'm not sure if the solution I'm about to propose is accurate or not =)
Regardless, here we go...

Are you trying to access the vector through a pointer?

When vectors are re-sized dynamically (using push_back() for instance), the "newly sized" vector is moved to a completely different location in memory. Assuming that your vector has not been declared with a "pre set" size (or assuming that you're exceeding this size), it will be dynamically re-sized when it is updated with data from your fstream.

So, if you're trying to access the vector through a pointer, the pointer is pointing to the ORIGINAL memory location of the vector, NOT the new location where the vector actually resides.

The reason an array works is because they are static in their size and memory locations. You cannot dynamically re-size an array, therefore, if will always remain at the same location in memory, and any pointer pointing at the array will work.


Whoa, sounds good! But, this also means bad stuff for me. Do you know how I can dynamically retrieve the new location of the vector without having to use a statically-sized variable? Turns out I'm having a few problems later on in my programming career, as I never got to learn much of the STL library.

Share this post


Link to post
Share on other sites
Quote:

Whoa, sounds good! But, this also means bad stuff for me. Do you know how I can dynamically retrieve the new location of the vector without having to use a statically-sized variable? Turns out I'm having a few problems later on in my programming career, as I never got to learn much of the STL library.

"Dynamically retrieving the new location of the vector" is going about things in the wrong fashion, almost certainly. Show us the code you're using now that is breaking, and we'll tell you what's wrong with it.

Be careful with your terminology. What you usually want when serializing a vector is the data contained in the vector -- not the vector itself. Therefor, the "location of the vector" is not germane the to the discussion. You want the location of the data, which you can get at via &myVector[0]. But you cannot persist that resulting address for long, because changes to the vector may invalidate it. You can, however, use it to serialize the vector data (although you don't need to, you can also walk the vector and serialize each data element).

Serialization in C++ can be tricky, it's full of gotchas because of the various bits of undefined behavior in the language -- for example, writing structs or class directly is brittle and prone to breakage.

Show us what you're actually doing.

Share this post


Link to post
Share on other sites
Here are the important bits of the code (This is from a different file, but it gives me the same error);


#include <fstream>
#include <vector>
#include <iostream>

int main() {
std::vector<int> first(5);
std::vector<int> second(5);
//For this example, I have static vectors. In my real program my vector is resized by a value read in through an ifstream
for(unsigned int i = 0; i < second.size(); i++) {
second[i] = i;
}

std::ifstream reader("foo.data", std::ios::binary);
reader.read((char *) &first, sizeof(first));
reader.close();

std::cout << first[0] << std::endl; //This is what gives me a segmentation fault

std::ofstream writer("foo.data", std::ios::binary);
writer.write((char *) &second, sizeof(second));
writer.close();

return 0;
}



According to you guys, I should be accessing the elements of the vector, and not the vector itself. Am I right in thinking this? Also, with this test application, I found out that I am getting a segmentation fault at the end (with the returning of main), even if I don't try to access any element of my "first" vector.

Share this post


Link to post
Share on other sites
By the way, you guys, my vector only stopped working once I converted to binary files. Previously, I wrote each element of the vector into a text file. At that time, it worked. Should I also be writing in the elements of the vector into the binary file, and not the vector itself?

Share this post


Link to post
Share on other sites
Quote:
Original post by JoeMagoe
By the way, you guys, my vector only stopped working once I converted to binary files. Previously, I wrote each element of the vector into a text file. At that time, it worked. Should I also be writing in the elements of the vector into the binary file, and not the vector itself?

Yes.

What you are experiencing now is the difference between POD data and more complex types. POD types can be written and read as raw data relatively safely on the same machine. However, such raw data is cannot be reliably read across different platforms. This is because the size of various data types (such as int) can differ, as well as endian issues (the order of bytes in a multi-byte value).

The safest way is to use explicitly sized types with a known endianness.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this