Segfault while reading/writing to binary files

Hi guys,

I'm using the g++ compiler on a Ubuntu virtual machine it could be 32 bit but not too sure on that one,

any how, it( writing and reading from bin files) seems to be a lot different (or at least seems a lot different ) in contrast to when I'm using windows.

I keep on getting seg faults and can't seem to figure out the issue, first I thought maybe the sizeof operator was not doing it's job because for strOne it tells me it's size is 8, which it's not! strOne is 9 chars long and must include a '\0' terminating character so it's really 10 bytes, not sure why sizeof(strOne) is telling me 8?

so then I decided to switch to strlen and added one for the null terminating byte, but yet still when I'm reading from my binary file I get a seg fault, I can't seem to figure out why this is happening :/ the arithmetic looks correct to me.

thanks

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

int main(){

// binary files
    
    fstream outBin;
    outBin.open("outBin.bin",ios::out | ios::binary);
    
    if(!outBin.is_open()){
        
        cout << "error opening binary file" << endl;
    }
    
    char* strOne = "hello bin";
    char* strTwo = "hey bin";
    int number = 619;
    char* strThree = "hi bin";
    
    int oneSize = strlen(strOne)+1;
    int twoSize = strlen(strTwo)+1;
    int threeSize = strlen(strThree)+1;
    // also tried sizeof() to get size of each string but to no avail
    
     cout << oneSize << endl;
     cout << twoSize << endl;
     cout << threeSize << endl;
     cout << "int" << sizeof(int) << endl;
    
    
    outBin.write(strOne,oneSize);
    outBin.write(strTwo,twoSize);
    outBin.write((char*)(&number),sizeof(int));
    outBin.write(strThree,threeSize);
    
    outBin.close();
    
    fstream inBin;
    inBin.open("outBin.bin",ios::in | ios::binary);
    
    if(!inBin.is_open()){
        
        cout << "error openening bin file" << endl;
    }
    
    char* one = new char(oneSize);
    char* two;
    char* three;
    int num;
    
    inBin.read(one,oneSize);
    
    cout << one << endl;
    
    inBin.read(two,twoSize);
    cout << two << endl;
    inBin.read((char*)&num,sizeof(int));
    inBin.read(three,threeSize);
}
Your problem is that you are writing to a uninitialized pointer with no memory. Please turn on your compiler warnings you would have seen it tell you there are uninitialized values.

Just -Wall is good, but -Wextra -pedantic may have a few obscure ones, but the more the merrier.

Also memory leaks and I think you have to return 0 on linux as a good practice.

And you should be using gdb for every C level error like segfaults and other faults, ideally this is why you want to use an IDE, since an IDE will show you the variables inside a function, will make break points + stepping very easy to use, and the stack trace will be immediately presented. gdb's syntax is quite painful, you have to do
1. gdb "PATH TO EXECUTABLE"
2. run
3. bt

It isn't hard obviously, but it is not as easy as pressing "debug button" when you get the same error 200 times in a row, and I still consider the breakpoint as the 2nd best tool for debugging after a stack trace (which is how you can get the values inside the scope of a function instead of caveman printing everything, but caveman printing can be helpful for fast moving programs still).
Last edited on
To repeat poteto (my name checks out) in other words:

1
2
3
4
5
6
7
8
9
    char* two;
    char* three;
    int num;
    
    inBin.read(one,oneSize);
    
    cout << one << endl;
    
    inBin.read(two,twoSize);

In that last line, what memory are you writing into? When was that memroy allocated to you?
> first I thought maybe the sizeof operator was not doing it's job because for
> strOne it tells me it's size is 8
keep in mind that sizeof is a compile time operator
this is your declaration char* strOne = "hello bin";
`strOne' is a pointer, the size of a pointer in your machine is 8
it does not mater to where it's pointing, its size will not change

perhaps you mean char strOne[] = "hello bin";
there, `strOne' is an array, so its size is n_elements * sizeof element

also, you can't modify a string literal, so you shouldn't be able to point a non-const pointer to it.



another thing
char* one = new char(oneSize);
you are allocating space for just one character, and you initialise it with the value `oneSize'
perhaps you mean to use brackets instead
char* one = new char[oneSize];
thanks guys

so the code below works

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
char* one = new char(oneSize);
    char* two = new char(twoSize);
    char* three = new char(threeSize);
    int num;
    
    inBin.read(one,oneSize);
    
    cout << one << endl;
    
    inBin.read(two,twoSize);
    cout << two << endl;
    inBin.read((char*)&num,sizeof(int));
    inBin.read(three,threeSize);
    cout << three << endl;


but as ne555 says you need to allocate a c style string as in an array
char* one = new char[oneSize]

but how come char* one = new char(oneSize);

worked for me? just by chance?

also lets say I wanted to create some c style strings on the stack instead of the free store like the above examples,( read data into c style strings on the stack and not on the heap like in my example)

so
1
2
3
4
5

char* strOne = "hello bin";
char* strTwo = "hey bin";
char* strThree = "hi bin";


I tried by creating an empty string

1
2
3
4
5

char* one = " ";
char* two = " ";
char* three = " ";


I guess this won't work because we are essentially writing past our string buffer in all three cases. what would be the way around this? since char is a primitive there is no resize function like std::string owns.

is there a function we can use to resize the string maybe in another header that we can use to resize c style strings?

`strOne' is a pointer, the size of a pointer in your machine is 8
it does not mater to where it's pointing, its size will not change


I was thinking the same but isn't 8 bytes kind of big for a char pointer? an int is only 4 bytes on my machine, 8 bytes kind of seems excessive - edit** silly me it's a 64 bit machine therefore it will be 8 bytes and will be 4 on a 32 bit system

thanks
Last edited on
It works because when you allocate memory all you have is a pointer, nothing is stopping you from accessing more than you should since no checking is done, this is also true with stack memory (as in fixed sized arrays). If you read far enough eventually you will get a seg fault because when you allocate memory, the OS gives the process a chunk of memory, and if you read outside the chunks the OS will notice, this is why memory leaks never linger after a process dies, because the OS just frees the chunks, not every individual call to the free store. But for your sanity, you need to accept that in C/C++ the result is not important, the responsibility is always put on the user to write correct code, having a "just works" personality with your code will cause you way more headaches than how another language would handle.

For linux you have valgrind which is a suite of many things, and I think memcheck is what you use for memory corruption like this, and for msvc these errors will be handled usually by just turning on the debug profile.

Of course in reality this is why people like using std::vector and never using it's [] operator instead using the .at() function since an exception is better than nothing.
> also lets say I wanted to create some c style strings on the stack instead of
> the free store like the above examples,( read data into c style strings on the
> stack and not on the heap like in my example)
>
> I tried by creating an empty string
> char* one = " ";
>
> I guess this won't work because we are essentially writing past our string
> buffer in all three cases. what would be the way around this? since char is a
> primitive there is no resize function like std::string owns.

as I said earlier «you can't modify a string literal, so you shouldn't be able to point a non-const pointer to it»
you compiler should have complained about char* one = " "; and perhaps even suggest const char* one = " ";
the problem is that that memory is not writable

you may simply reserve enough writable memory with char one[42];
of course, if `oneSize' ends up being bigger than 42, then you will write out of bounds.
Last edited on
Topic archived. No new replies allowed.