Run Time Error

Hi all.Please, help me with an run-time error.
I need to create a file and put a string in it.My string lenght is set by a constant [MAX_SIZE] from a class.While introducing data in input stream, an Run-Time Error appears.It says:
Run-Time Check Failure #2 - Stack around the variable 'Pstream' was corrupted.

Here is the code:

struct cpyDataPassword
{
enum {MAX_SIZE = 3};
char str [MAX_SIZE];
string old_pwd;
};
ofstream PFile("file.file");
void *ptrPassword = &Pw;// Getting the address of the object: Password
cpyDataPassword *ptrData = (cpyDataPassword*)ptrPassword;// type-casting the address of Password to *cpyDataPassword

char Pstream[ptrData->MAX_SIZE], *P = Pstream;
while((*P++=getchar()) != '\n');
for(int i=0;i!=ptrData->MAX_SIZE;i++)
{
PFile.put(Pstream[*P]);
}

All information which you know about this - will be useful for me.
use [co de][/co de] tags, without the spaces.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#include<iostream>
#include<string>
#include<fstream>
using namespace std;

struct cpyDataPassword
{
enum {MAX_SIZE = 3};
char str [MAX_SIZE];
//string old_pwd; // change it to a char arary, it is not good to have a string object here
};

int main()
{
	// create an object of your data
	cpyDataPassword Pw;
	Pw.str[0]='a'; // or iterate to fill
	Pw.str[1]='b';
	Pw.str[2]='c';

// 1. Write file
	ofstream PFile;
	PFile.open("file.file", ios::out | ios::binary); // in binary mode
	if(PFile.is_open())
	{ 
		PFile.write(reinterpret_cast<char*>(&Pw),sizeof(cpyDataPassword));
		//PFile.write((char*)(&Pw),sizeof(cpyDataPassword));// also ok
		//It may be also possible to write member by member 
                                        PFile.close(); // after writig close it

	}else
	{
		cout << "Problem in opening file " << endl;
	}

// 2. Read file

	ifstream infile;
	infile.open("file.file", ios::out | ios::binary); // in binary mode
	cpyDataPassword fromFilepasswd; // to hold the object coming from file

	if(infile.is_open())
	{ 
		infile.read(reinterpret_cast<char*>(&fromFilepasswd),sizeof(cpyDataPassword));
		infile.close();
		//test print
		
		cout << fromFilepasswd.str[0] << "\t"; // or iterate to extract
		cout << fromFilepasswd.str[1] << "\t";
		cout << fromFilepasswd.str[2] << endl;

	}else
	{
		cout << "Problem in opening file " << endl;
	}



	return 0;
}
Last edited on
Don't read/write data structures. Especialy not if the data structure contains a complex object (like a string).

Bad bad bad.
I have written the code as a continution of what 'salex' has started.
But please explain reason to say don't read/ write data structures.
Last edited on
write() simply dumps binary data to a file. It says nothing about what that data represents or how it is stored, and therefore should only be used with basic data types. Some reasons for this are:

1) The compiler may rearrange and pad members of structures as it sees fit.

2) Complex data types like classes and structures may contain things you can't serialize, like vtables and maybe even RTTI (typeinfo()) information.

3) Classes/structs (such as std::string) may contain pointers to data, and may not actually contain the desired data themselves. So if you just try to write() a string, you actually don't write the string data, but end up writing a pointer to the string data (and probably some other stuff). When you read this string from the file, you simply read a pointer, but the pointer will then be garbage.

For example.. try the following:

1
2
3
4
5
    string foo = "This is an example string";

    ofstream f;
    f.open("file.txt", ios::out | ios::binary);
    f.write(reinterpret_cast<const char*>(&foo),sizeof(foo));


Open up file.txt and look at it. Notice that it doesn't contain "This is an example string" -- instead it's only a few bytes large, and those bytes are garbage. This is because you just wrote the pointer, and not the actual data.

If you attempt to read this file, you'll just read the pointer, but the pointer won't point to anything, and so you'll run into all sorts of runtime problems and program crashes.
Thank you, I agree all the points and another reson not to do is the string.length may not represent the actual block size.
I modified my post accordingly.
Last edited on
I'll try to change the code and post the results.
anilpanicker, the struct "cpyDataPassword" is used only to acces the class data which is private.
the row
PFile.write(reinterpret_cast<char*>(&Pw),sizeof(cpyDataPassword));

does not works properly.Also in this case, i can't obtain any output data using the getchar() in this
if(PFile.is_open())
{
string Pstream;while(getchar() != '\n'){PFile.write(reinterpret_cast<char*>(&Pw),sizeof(cpyDataPassword));
}

The same thing hapens with the example of Mr. Disch.
Maybe any other cases of storing a checked by lenght string into a file exists...?
1
2
3
4
5

if(PFile.is_open())
{ 
string Pstream;while(getchar() != '\n'){PFile.write(reinterpret_cast<char*>(&Pw),sizeof(cpyDataPassword));
}

I did not understand what you are doing here. In my code I tried to show you how to read and write data in to a file, which is written as a binary file. When you have a string member in your class/struct you need to be more carefull about write() because string obect's size needs to be calculated before writing the memory block also other issues Disch mentoned.

You may need to post your entire code and explain what you want to do.
Also while posting use the # mark on your right panel to paste your code
I had been escaped from run-time error.thank you.trouble was with pointered string which had been overflowed and garbaged.
but a new question appeared.
I can't write nothing in my file.here's the listing:
1
2
3
4
5
6
7
8
9
10
11
12
Password Pw;
	ofstream PFile("password.dat");
	puts("You are new user.\nPlease register.Type a new password below.");cout<<"Password: ";
	PFile.flush();
string Pstream;cin>>Pstream;
	if (!(PFile.is_open())) perror("Unable to open file");
	else if(!PFile.eof()&&(Pstream.length() == Pw.MAX_SIZE))perror("Wrong Password lenght.");
	cout<<"Password with "<<Pw.MAX_SIZE<<" digits required.Try again.\n";
	{
			PFile<<Pstream;
			puts("Password saved.\n");	
	}

what i must change here?
The conditional statements are not written correctly so I added some brackets and else statement.
Now it wries the password in to the file but the logic seems to be weird. It writes password when the user given password length is < or >, it doesn't write if it is equal. Is this what you want?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
                 Password Pw;
	ofstream PFile("password.dat");
	puts("You are new user.\nPlease register.Type a new password below.");cout<<"Password: ";
	PFile.flush();
string Pstream;cin>>Pstream;
	if (!(PFile.is_open())) perror("Unable to open file");
	else if(!PFile.eof()&&(Pstream.length() == Pw.MAX_SIZE))
               {
                perror("Wrong Password lenght.");
	cout<<"Password with "<<Pw.MAX_SIZE<<" digits required.Try again.\n";
                }
                else
	{
			PFile<<Pstream;
			puts("Password saved.\n");	
	}
i had corrected this code with
else if((!PFile.eof())&&(Pstream.length() != Pw.MAX_SIZE))
but the same thing happens: no data written.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include<fstream>
#include<iostream>
#include<string>
using namespace std;


int main()
{
	ofstream PFile("password.dat"); // creates and opens file
	if(PFile.is_open())
	{// file opened so do your actions
		string Pstream;  
		cout << "Yotu are new user.\nPlease register.Type a new password below." << endl;
		cout<<"Password: ";
		cin>>Pstream;
		//now you got user given password check it for validity
		while(Pstream.length() < 5) // loops if user given password length less than 5 characters
		{
			cout << "Wrong Password length, Password with "<<5<<" digits required.Try again.\n" << endl;
			cout<<"Password: ";
			cin>>Pstream;
		}
		// came out of loop since you have a password more than 5 char so write it to the file
		PFile << Pstream;
		cout << "Password saved" << endl;
		PFile.close(); 

	}else 
	{
		cout << "Error in opening file" << endl;
	}
	
return 0;
}



thank you a lot. this method works correctly.
Topic archived. No new replies allowed.