What it does is that it reads the information of some students from a (txt) file and writes them into another (bin) file .
The reason I'm writing this is that I'm just learning how to work with binary files (and I learnt)
BUT the problem is my program ran successfully , I mean it wrote all the first names of students (that means it could write the information in a binary file and could read them back) , but after writing their names , my program crashed .
I used output tests ( like cout << "TEST" ;) in every single line and ended up with that code I just wrote for you , in the output program , I see just one "TEST" and then the program crashes .
I have read that strings have problems with "read" and "write" functions and my class "Student" is full of strings , do you think that may cause it?
SIMPLY SPEAKING : In the code above I see just one TEST and the program crashes .
You can't simply write a vector's binary form directly to file and read it back like that. That's very likely screwing up its internal state; it could crash anywhere after that, it just is probably crashing when it is being destructed on the return.
Nothing after return 0; will or should ever be executed. return is an instruction to exit the function, and go back to the place where the function was called from. In this case your main function returns to part of the C++ library which called your main function.
So you are supposed to see only one "Test" printed. Your compiler ought to warn you about having something after return (which can never be executed).
Nothing after return 0; will or should ever be executed.
atexit() stuff and destructors are run.
Specifically... vector's destructor is where the crash is happening because of what Zhuge said: you can't write to a vector object directly like that.... it's corrupting memory.
EDIT:
Personally.. i'm of the opinion that you should never do a raw read/write of anything but individual bytes.
Now, vectors use heap storage for their elements, to they have a pointer to heap memory somewhere inside (the details are implementation specific) pointing at the block of memory where the elements are stored. By making a shallow copy you have ended up with two vectors which think they own the same block of (heap) memory.
So when the first vector's destructor fires is cleans up ok; but when the second destructor fries, the memory has already been freed and things go wrong.
(With the debug build of Visual C++ I get an assert telling me the heap block I'm trying to free isn't in use.)
You do understand that by writing the vector's body to disk that you haven't actually stored the data the vector owns? (The data stored on the heap.)
@Andy @Zhuge @Disch and @hitirwin THNX!
I read that article Disch gave it's link .
I almost understood why my program crashed .
So what can I do ?
According to that article I need to separate my vector to bytes and put them in file , (or something like that) but I have mop idea how to do that and how to read them back .
OR
I thought maybe I can create a temporary student object and assign all the students in vector to it one by one and for each one I write them to binary file .
'm not sure if it works , BUT I'm looking for a way to write the whole vector in file .
What should I do ?
Can I use other containers rather than VECTOR ?
THANK YOU ALL !
You know my problem is solved and I have no problem with the binary file , I chose another way to do that .
By the way The class Date is a normal Date class :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
class Date
{
private :
int Day ;
int Month ;
int Year ;
public :
Date () {} ;
Date (int D , int M , int Y) {Day = D ; Month = M ; Year = Y ;}
Date SetDate (int D , int M , int Y) {Day = D ; Month = M ; Year = Y ; return * this ;}
string ToString () {return itos (Year) + "/" + itos (Month) + "/" + itos (Day) ;} ;
void SetDay (int input) {Day = input ;}
int GetDay (int input) {return Day ;}
void SetMonth (int input) {Month = input ;}
int GetMonth (int input) {return Month ;}
void SetYear (int input) {Year = input ;}
int GetYear (int input) {return Year ;}
} ;
By temporary object I mean this :
1 2 3 4 5 6 7
vector <Student> iterator :: it ;
Student tmp ;
for (it = stus.begin () ; it != stus.end () ; it ++)
{
tmp = * it ;
stubin.write ((char *) & tmp , sizeof (Student)) ;
}
Reading and Writing from/to a file is in two separate function .
I am facing a new problem :
in the ReadFromFile function I put two cout << "TEST"s and just one of them is shown , that means the read function can't read the objects from file from file . :|
The read problem relates to the way strings work with pointer internally.
The only reason your save sort of works is because (for performance reasons), most std::string implementations keep short strings in a buffer internal to the class and only allocate a separate buffer on the heap if more storage is required.
For the Visual C++ version of the class, std::string can use up to 16 chars before heap allocation is used, whereas it's just 8 for wchar_t wstrings, including the null terminator. (So you'd better hope Cherry Chevapravatdumrong's children don't turn up to enrole!)
But the buffer is always accessed though a pointer, which is initialized to point at the buffer, and then updated to point at heap memory later on, if additional storage space is required.
Now, a pointer has to point at a specific address. So if you copy from your binary file into a Student which is located in a different place in memory to when you saved the data, then you might put the string value into the new buffer, but you won't correctly set the pointer to point at this new buffer; the pointer value will still correspond to the location where the buffer was when you saved the student to file.