Search code examples
c++segmentation-faultfstreambinaryfiles

Improper Understanding of Segmentation Fault


I get a segmentation fault and from what I've read, it's due to me trying to access some part of memory I am not allowed to.

I'm nearly certain my problem is arising in the while loop inside of my ShowAccounts function.

while (input.read((char *) &account, sizeof(BankAccount)))

After multiple attempts to understand just how this call to read works, I don't think I am understanding it correctly.

I have already created 3 accounts of type BankAccount and they are stored in the binary file AccountDetails.dat, however, I am unable to access them.

If you can't help with the overall reasoning as to why I'm receiving this segmentation fault, maybe you could explain just how the read function works and what all it is attempting to do and then I can do some more evaluating? Any and all responses are welcomed.

#include <iostream>
#include <fstream>
using namespace std;

class BankAccount
{
public:
    void CreateAccount();
    void ShowAccount();
private:
    int accountNumber;
    string firstName;
    string lastName;
    char accountType;
    double balance;
};

void MakeAccount();
void ShowAccounts();

int main()
{
    ShowAccounts();

    return 0;
}

void BankAccount::CreateAccount()
{
    cout << "Enter the account number.\n";
    cin >> accountNumber;
    cout << "Enter the first and last name of the account holder.\n";
    cin >> firstName >> lastName;
    cout << "What kind of account is it? S for savings or C for checking.\n";
    cin >> accountType;
    cout << "How much are you depositing into the account?\n";
    cin >> balance;
    cout << "CREATED\n";
}

void BankAccount::ShowAccount()
{
    cout << "Account Number:  " << accountNumber << endl;
    cout << "Name:  " << firstName << " " << lastName << endl;
    cout << "Account Type:  " << accountType << endl;
    cout << "Current Balance:  $" << balance << endl;
}

void MakeAccount()
{
    BankAccount account;
    ofstream output;
    output.open("AccountDetails.dat", ios::binary|ios::app);
    if (!output)
        cerr << "Failed to open file.\n";
    account.CreateAccount();
    output.write((char *) &account, sizeof(BankAccount));
    output.close();
}

void ShowAccounts()
{
    BankAccount account;
    ifstream input;
    input.open("AccountDetails.dat", ios::binary);
    if (!input)
        cerr << "Failed to open file.\n";
    while (input.read((char *) &account, sizeof(BankAccount)))
    {
        account.ShowAccount();
    }
    input.close();
}

Solution

  • When you try to read bytes from an input stream directly onto a structure containing pointers or strings, you will set the pointers they contain to garbage. (Arrays of characters will work.) Attempting to use the pointers and strings will then cause undefined behavior, which might cause a segmentation fault to happen. Or anything else.

    To check this, load the program in a debugger, set a breakpoint on that line, and run. When you get there, inspect the structure and its members to see if the data they contain is valid.

    Try adapting your BankAccount::CreateAccount() function to be non-interactive.