Unexpected SIGABRT at return 0

I am working through Binary IO with objects and am running into a curious error.

The program executes perfectly until it hits the very end. At "return 0", the program fails. The debugger picks up SIGABRT when executing "return 0". This seems to me to indicate a deconstructor problem of some kind. However, I can't seem to find any deconstructor problems (I am fairly new at programming though).

If I comment out the following two lines:

"binaryio.read(reinterpret_cast<char *>(&studentNew1), sizeof(Student));"
"binaryio.read(reinterpret_cast<char *>(&studentNew2), sizeof(Student));"

then the program finishes exiting without error . . . . but the whole point is to be able to read from the binary file. With those two lines in the code, the program successfully reads from the file and outputs the objects to the console ,but fails at "return 0";

I'd appreciate any help you guys can give!

Thanks,
ReadingWord

Here is the code:

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
#include <iostream>
#include <fstream>
#include "Student.h"
using namespace std;

void displayStudent(Student student)
{
    cout << student.getFirstName() << " ";
    cout << student.getMi() << " ";
    cout << student.getLastName() << " ";
    cout << student.getScore() << endl;
};

int main()
{
    fstream binaryio; // Create stream object
    binaryio.open("student.dat", ios::out | ios::binary);
    
    
    Student student1("John", 'T', "Smith", 90);
    
    Student student2("Eric", 'K', "Jones", 85);
    
    binaryio.write(reinterpret_cast<char *>(&student1), sizeof(Student));
    
    binaryio.write(reinterpret_cast<char *>(&student2), sizeof(Student));
    
    binaryio.close();
    
    // Read student back from the file
    binaryio.open("student.dat", ios::in | ios::binary);
    
    Student studentNew1 = Student("Jo", 'T', "Schmo", 99);
    
    Student studentNew2 = Student("Jo", 'T', "Schmo", 99);
    
    binaryio.read(reinterpret_cast<char *>(&studentNew1), sizeof(Student));
    
    displayStudent(studentNew1);
    
    binaryio.read(reinterpret_cast<char *>(&studentNew2), sizeof(Student));
    
    displayStudent(studentNew2);
    
    binaryio.close();
    
    return 0;
    
};


And here is the Student.h file

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
#ifndef STUDENT_H
#define	STUDENT_H

#include <string>
using namespace std;

class Student  
{
public:
    Student();
    Student(string firstName1, char mi1, string lastName1, int score1);
    ~Student();
    string getFirstName();
    char getMi();
    string getLastName();
    int getScore();
    void setFirstName(string newFirstName);
    void setMi(char newMiddleInitial);
    void setLastName(string newLastName);
    void setScore(int newScore);
    
private:
    string firstName;
    char mi;
    string lastName;
    int score;

};

#endif	/* STUDENT_H */


And here is the Student.cpp file

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
#include "Student.h"

// Construct default student
Student::Student()
{
    
};

// Construct a Student object with specified data
Student::Student(string firstName1, char mi1, string lastName1, int score1)
{
    firstName = firstName1;
    mi = mi1;
    lastName = lastName1;
    score = score1;
};

Student::~Student()
{
    
};

string Student::getFirstName()
{
    return this->firstName;
};

char Student::getMi()
{
    return this->mi;
}

string Student::getLastName()
{
    return this->lastName;
};

int Student::getScore()
{
    return this->score;
};

void Student::setFirstName(string newFirstName)
{
    this->firstName = newFirstName;
};

void Student::setMi(char newMiddleInitial)
{
    this->mi = newMiddleInitial;
};

void Student::setLastName(string newLastName)
{
    this->lastName  = newLastName;
};

void Student::setScore(int newScore)
{
    this->score = newScore;
};
Last edited on
You are trying to read an std::string.
You mess with the internals of the object and leave it in an invalid state. When the string is destroyed it tries to release memory that never owned.
ne555, I really appreciate you taking the time to look through my program and identify the memory release problem.

I attempted to understand and fix the problem based on what you said, but I am lost. If I include an overwrite for newStudent1 and newStudent2 right before "return 0" with legitimate values it does not give me a SIGABRT but it does give a segmentation error :(
So I don't really understand what is going on well enough to fix the problem without creating another.

Specifically, how am I giving the firstName and lastName strings an invalid state? When I think of an invalid state I think of giving the string an int or some other invalid value--however, in my case the first and last names are printed to the screen correctly so I don't comprehend what is making them invalid when they contain printable strings. Is it worth looking into this more or should I come back to it when I am more familiar with C++?

Thanks,
ReadingWord
Last edited on
std::string has a pointer. When you write a string. you write that pointer.

When you read the file, you took that memory address. However ¿what values are at that address?
You lose the content of the string.
(in your case you've got two strings pointing to the same address, producing a double delete that makes your program crash)

You should write the content instead, firstName.c_str()
Reading has it issues too, to simplify use a buffer of enough length, zero terminated. Then copy it to the string.

Also, take a look at this thread http://www.cplusplus.com/forum/beginner/76800/
Specifically, how am I giving the firstName and lastName strings an invalid state?

By doing: binaryio.read(reinterpret_cast<char *>(&studentNew1), sizeof(Student));

If we had our own version of string and the data members of it looked something like:

1
2
3
4
5
struct mystring
{
    char* text ;
    unsigned size ;
};


do you think we should be writing the pointer value to the file, or the text the pointer is pointing to? If we write the pointer value to the file, do you think when we attempt to read it back into memory that the contents originally pointed to will be at the same address? Do you think that will still be a valid memory address?

Might want to take a gander at:
http://stackoverflow.com/questions/7046244/serializing-a-class-which-contains-a-stdstring
Thanks ne555! timer! :)
That makes sense. Since I am copying the exact binary of one object to another object (just with a different name), both objects will reference the same memory for their members and this is a problem when they are deconstructed.
Thanks also for the thread link for learning to do binary IO properly!

cire, thank you as well! ne555 barely beat you to the punch :)
Topic archived. No new replies allowed.