error while creating and copying a binary file with strings

Hello everyone.

here's a program that stores some string data in a binary file , read them and then write them to another file. Along with each string I write its length , so when I read them later , I know what size i have to use.

Well , the fact is this works well but it's unstable, bacause finally it cause a segmentation fault when i wrtie three different strings. For example with two strings it doesn´t matter.

This is the entire code that compiles. It's commented and it indicates where the error jumps when debugging.

Thank you in advance.

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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#include <iostream> 
#include <string>  
#include <fstream>  


using namespace std;

int main()
{FILE*  fileFrom; //file created to be source
 FILE* fileTo; //file created to be destination
 string m_string1; //first string variable
 string m_string2; //second string variable
  string m_string3; //third string variable

 fileFrom=fopen("c:/file_From.cbin","wb+"); //we create the file_From, writing the string values and its lengths
 int m_integer1;
 int m_integer2,m_integer3;
 m_string1="first string";
 m_string2="second string is very much longer than the first one, as you easily can see";
 m_string3="third string is very much longer than the first one, too";
  
 m_integer1=m_string1.length();
 m_integer2=m_string2.length();
 m_integer3=m_string3.length();
     
 //now we write first the length, after that, the string itself
 fwrite((char*)&m_integer1,sizeof(int),1,fileFrom);
  fwrite((char*)&m_string1,sizeof(char),m_integer1,fileFrom);
  fwrite((char*)&m_integer2,sizeof(int),1,fileFrom);
 fwrite((char*)&m_string2,sizeof(char),m_integer2,fileFrom);
   fwrite((char*)&m_integer3,sizeof(int),1,fileFrom);
 fwrite((char*)&m_string3,sizeof(char),m_integer3,fileFrom);
  
 fclose(fileFrom);
 
   string string_from1,string_from2,string_from3;  //created to store the value read from file_From in the following steps,  
  
  
  fileFrom=fopen("c:/file_From.cbin","rb+");
  fileTo=fopen("c:/file_To.cbin","wb+");
  //Noe we're going to read data from the first file and store the values in the new variables, 
  //to write them into another file, a copy of the first one..
  fread((char*)&m_integer1,sizeof(int),1,fileFrom);
  fwrite((char*)&m_integer1,sizeof(int),1,fileTo);
  
  fread((char*)&string_from1,sizeof(char),m_integer1,fileFrom);
  fwrite((char*)&string_from1,sizeof(char),m_integer1,fileTo);
 
  fread((char*)&m_integer2,sizeof(int),1,fileFrom);
  fwrite((char*)&m_integer2,sizeof(int),1,fileTo);
 
  fread((char*)&string_from2,sizeof(char),m_integer2,fileFrom);
  fwrite((char*)&string_from2,sizeof(char),m_integer2,fileTo);
 
 
   fread((char*)&m_integer3,sizeof(int),1,fileFrom);
  fwrite((char*)&m_integer3,sizeof(int),1,fileTo);
 
  fread((char*)&string_from3,sizeof(char),m_integer3,fileFrom);
  fwrite((char*)&string_from3,sizeof(char),m_integer3,fileTo);
 
  fclose(fileFrom);
  fclose(fileTo);
  //now we check if the values written are ok
    fileTo=fopen("c:/file_To.cbin","rb+");
    fread((char*)&m_integer1,sizeof(int),1,fileTo);
    cout<<m_integer1<<endl;
  
  fread((char*)&string_from1,sizeof(char),m_integer1,fileTo);
  cout<<string_from1<<endl;
 
  fread((char*)&m_integer2,sizeof(int),1,fileFrom);
  cout<<m_integer2<<endl;
 
  fread((char*)&string_from2,sizeof(char),m_integer2,fileTo);
  cout<<string_from2<<endl;
  
fread((char*)&m_integer3,sizeof(int),1,fileTo);
  cout<<m_integer3<<endl;
 //here jumps the segmentation fault at debugging
  fread((char*)&string_from3,sizeof(char),m_integer3,fileTo);
  cout<<string_from3<<endl;
     
    fclose(fileTo);
return 0;} 
Last edited on
On line 65 and line 84 you open and close fileTo, but you make all your reads from fileFrom...
thank you, I didn´t see it. It's already changed in the first post. The problem is the same, anyway. This error ocurrs in another project, but to make it more easy I wrote a program that reproduce the situation. Thanks again.
This doesn't do what you think it does.:

 
fread((char*)&string_from1,sizeof(char),m_integer1,fileFrom);


That line will cause the data being read in from the file to overwrite the string object.

That is very bad.

What you need to do is populate the string from the information in the file.

So you need to read in the data from the file into a character buffer first and then put that into the string.
Likewise with this line:

 
fwrite((char*) &m_string1, sizeof(char), m_integer1, fileFrom);


You are writing the string object to the file rather than the data contained in the string.

You would need something more like this:


 
fwrite(m_string1.c_str(), sizeof(char), m_integer1, fileFrom);


That is because the function m_string1.c_str() returns the data from inside the string object as a char*

perhaps I didn´t understand something..

If I use first to write

fwrite(m_string1.c_str(), sizeof(char), m_integer1, fileFrom);

and then I read to a char* variable like this

1
2
char* char_from1;
fread(char_from1,sizeof(char),m_integer1,fileFrom);


I get a segmentation fault error in the fread line.

thank you very much.
Last edited on
This is better:

1
2
char* char_from1;
fread(char_from1,sizeof(char),m_integer1,fileFrom);


But the reson it doesn't work is because you have not allocated any memory to your char* char_from1.

So it is pointing to some random place in memory!

A better method might be this:


1
2
3
4
5
6
7
char char_from1[m_integer1]; // allocate enough memory for the string data

fread(char_from1,sizeof(char),m_integer1,fileFrom); // reas the data into the space pointed to by char_from1

std::string string_from1;

string_from1.assign(char_from1, m_integer1); // copy that data from char_from1 into the string. 

Note that if you want to use char_from1 as a cstring you need to add a '\0' character to the end of it.

So you would need to make it one character bigger than the size of the data like this:

1
2
3
4
5
6
char char_from1[m_integer1 + 1]; // allocate enough memory for the string data + the '\0' end char

fread(char_from1,sizeof(char),m_integer1,fileFrom); // reas the data into the space pointed to by char_from1

char_from1[m_integer1] = '\0'; // then add the '\0' end char to make it into a cstring.
What would be worth while is writing the read and write operations into functions a bit like this:

1
2
3
4
5
6
7
8
9
10
void write_string(FILE* file, const std::string& str)
{
	// code to output a string in binary format
}

std::string read_string(FILE* file)
{
	// code to read in a string from binary format
}
Last edited on
perfect!! It works. Certainly it's worth to write a specific function for that.I'll do it. Thank you again.

Topic archived. No new replies allowed.