Strange seg fault

Sorry, I know that this is a column with an error in the "Stack Overflow" section, but I tried a few days to fix this code and I am at a dead end, so I decided to contact you guys. Hope you can help!

Anyway, I get weird segfault in this code:

account.h (Note. I am not allowed to modify the account.h file in any way as intended. :)

class account { public: typedef char* string; static const size_t MAX_NAME_SIZE = 15; // CONSTRUCTOR //account(); account (char* i_name, size_t i_acnum, size_t i_hsize); account (const account& ac); // DESTRUCTOR ~account ( ); // MODIFICATION MEMBER FUNCTIONS void set_name(char* new_name); void set_account_number(size_t new_acnum); void set_balance(double new_balance); void add_history(char* new_history); // CONSTANT MEMBER FUNCTIONS char* get_name () const; size_t get_account_number ( ) const; double get_balance( ) const; size_t get_max_history_size( ) const; size_t get_current_history_size ( ) const; string* get_history() const; friend std::ostream& operator <<(std::ostream& outs, const account& target); private: char name[MAX_NAME_SIZE+1]; //name of the account holder size_t ac_number; //account number double balance; //current account balance string* history; //Array to store history of transactions size_t history_size; //Maximum size of transaction history size_t history_count; //Current size of transaction history }; 

account.cxx:

 #include <string.h> #include <cassert> #include <cstdlib> #include <iostream> #include "account.h" using namespace std; account::account(char* i_name, size_t i_acnum, size_t i_hsize) { assert(strlen(i_name) <= MAX_NAME_SIZE); strcpy(name, i_name); ac_number = i_acnum; history_size = i_hsize; balance = 0; history_count = 0; history = new string[history_size]; } account::account(const account& ac) { strcpy(name, ac.name); ac_number = ac.ac_number; balance = ac.balance; history = new string[ac.history_size]; for(size_t i = 0; i < ac.history_count; i++) { history[i] = new char[strlen(ac.history[i]) + 1]; strcpy(history[i], ac.history[i]); } history_count = ac.history_count; history_size = ac.history_size; } account::~account() { delete[] history; } void account::set_name(char* new_name) { assert(strlen(new_name) <= MAX_NAME_SIZE); strcpy(name, new_name); } void account::set_account_number(size_t new_acnum) {ac_number = new_acnum;} void account::set_balance(double new_balance) {balance = new_balance;} void account::add_history(char* new_history) { assert(history_count < history_size); history[history_count] = new char[strlen(new_history) + 1]; strcpy(history[history_count], new_history); history_count++; } char* account::get_name() const { char* blah = new char[MAX_NAME_SIZE + 1]; strcpy(blah, name); return blah; } size_t account::get_account_number ( ) const {return ac_number;} double account::get_balance( ) const{return balance;} size_t account::get_max_history_size( ) const {return history_size;} size_t account::get_current_history_size ( ) const {return history_count;} account::string* account::get_history() const { string* blah = new string[history_size]; for(size_t i = 0; i < history_count; i++) { blah[i] = new char[strlen(history[i]) + 1]; strcpy(blah[i], history[i]); } return blah; } std::ostream& operator<< (std::ostream& outs, const account& target) { outs << "Name: " << target.name << "\n" << "Account Number: " << target.ac_number << "\n" << "Balance: " << "$" << target.balance << "\n" << "History: "; for(size_t i = 0; i < target.history_count; i++) { outs << target.history[i] << "\n"; } outs << "Current History Size: " << target.history_count << "\n"; outs << "Max History Size: " << target.history_size << "\n"; return outs; } 

bankledger.h

 class bank_ledger { public: static const int MAX_ACC_SIZE = 15; bank_ledger(int mo, int mc); bank_ledger(const bank_ledger& copyledger); ~bank_ledger(); void create_account(char* i_name, size_t i_acnum, size_t i_hsize); void close_account(double accnum); double balance_of(double accnum); void deposit(double accnum, double money); void withdraw(double accnum, double money); void transfer(double accnum1, double accnum2, double money); void print_account_history(double accnum); void print_account_details(double accnum); void print_current_details(); void print_closed_details(); account* lookup(double accnum); private: account** open; account** closed; int max_open; int max_closed; int num_open; int num_closed; }; 

bankledger.cxx:

 #include <cstdlib> #include <iostream> #include <cassert> #include "account.h" #include "bank_ledger.h" using namespace std; bank_ledger::bank_ledger(int mo = 30, int mc = 30) { max_open = mo; max_closed = mc; open = new account*[max_open]; closed = new account*[max_closed]; num_open = 0; num_closed = 0; } bank_ledger::bank_ledger(const bank_ledger& copyledger) { int i; max_open = copyledger.max_open; max_closed = copyledger.max_closed; num_open = copyledger.num_open; num_closed = copyledger.num_closed; open = new account*[num_open]; closed = new account*[num_closed]; for(i = 0; i < max_open; i++) { if (i < num_open) open[i] = copyledger.open[i]; } for(i = 0; i < max_closed; i++) { if (i < num_closed) closed[i] = copyledger.closed[i]; } } bank_ledger::~bank_ledger() { for(int i = 0; i < num_open; i++) { delete open[i]; } for(int i = 0; i < num_closed; i++) { delete closed[i]; } delete[] open; delete[] closed; } account* bank_ledger::lookup(double accnum) { for(int i = 0; i < num_open; i++) { if(open[i]->get_account_number() == accnum) { return *open + i; } if(closed[i]->get_account_number() == accnum) { return *closed + i; } } } void bank_ledger::create_account(char* i_name, size_t i_acnum, size_t i_hsize) { assert(num_open < max_open); open[num_open] = new account(i_name, i_acnum, i_hsize); open[num_open]->add_history("Account Created"); num_open++; } void bank_ledger::close_account(double accnum) { int i; double temp = -1; cout << *(open[0]) << endl << "Good Idea" << endl; account* acc = lookup(accnum); for(i = 0; i < num_open; i++) { if(open[i]->get_account_number() == acc->get_account_number()) { temp = i; closed[num_closed] = open[i]; for(i = temp; i < num_open - 1; i++) { open[i] = open[i+1]; } closed[num_closed]->add_history("Account Closed"); num_open--; num_closed++; return; } } } double bank_ledger::balance_of(double accnum) { return lookup(accnum)->get_balance(); } void bank_ledger::deposit(double accnum, double money) { account* acc = lookup(accnum); acc->set_balance(acc->get_balance() + money); acc->add_history("Deposited $"); } void bank_ledger::withdraw(double accnum, double money) { account* acc = lookup(accnum); acc->set_balance(acc->get_balance() - money); acc->add_history("Withdrew $"); } void bank_ledger::transfer(double accnum1, double accnum2, double money) { withdraw(accnum2, money); deposit(accnum1, money); } void bank_ledger::print_account_history(double accnum) { account* acc = lookup(accnum); account::string *hist = acc->get_history(); cout << "History of " << acc->get_name() << " account: " << endl; for (int i = 0; i < acc->get_current_history_size(); i++) cout << hist[i] << endl; } void bank_ledger::print_account_details(double accnum) { account* acc = lookup(accnum); cout << *acc; cout << "\n"; } void bank_ledger::print_current_details() { for(int i = 0; i < num_open; i++) { cout << *open[i] << "\n"; } } void bank_ledger::print_closed_details() { for(int i = 0; i < num_closed; i++) { cout << *closed[i] << "\n"; } cout << "\n"; } 

sample_test_input2.cxx

 #include <cstdlib> #include <iostream> #include "account.h" #include "bank_ledger.h" using namespace std; int main() { bank_ledger bl(30, 30); bl.create_account("name1", 1, 30); bl.create_account("name2", 2, 30); bl.create_account("name3", 3, 30); bl.create_account("name4", 4, 30); bl.print_current_details(); bl.close_account(2); return 0; } 

Valgrind and GDB say that * (open [i]) is not initialized. Here's the exact output of Valgrind:

 ==7082== Use of uninitialised value of size 8 ==7082== at 0x1000018C6: account::get_account_number() const (account.cxx:74) ==7082== by 0x10000246B: bank_ledger::lookup(double) (bank_ledger.cxx:85) ==7082== by 0x1000027D0: bank_ledger::close_account(double) (bank_ledger.cxx:105) ==7082== by 0x100003117: main (sample_test_input2.cxx:17) ==7082== ==7082== Invalid read of size 8 ==7082== at 0x1000018C6: account::get_account_number() const (account.cxx:74) ==7082== by 0x10000246B: bank_ledger::lookup(double) (bank_ledger.cxx:85) ==7082== by 0x1000027D0: bank_ledger::close_account(double) (bank_ledger.cxx:105) ==7082== by 0x100003117: main (sample_test_input2.cxx:17) ==7082== Address 0x10 is not stack'd, malloc'd or (recently) free'd 

It goes from main to bankledgrer::close_account , to bankledger::lookup , and then it crashes with if(open[i]->get_account_number() == accnum)

If I stick with cout << *(open[i]) right before this line, it prints it in order. I'm afraid I'm at a loss. Any help would be greatly appreciated. If you want me to include header files, or clarify something, please let me know.

PS. In addition, I know that this code is very C, but as my professor wants, although it is a C ++ class. Go figure.: \

+4
source share
1 answer

In this method:

 account* bank_ledger::lookup(double accnum) { for(int i = 0; i < num_open; i++) { if(open[i]->get_account_number() == accnum) { return *open + i; } if(closed[i]->get_account_number() == accnum) { return *closed + i; } } } 

Do you think that the number of closed accounts is at least the same as the number of open accounts. You have to iterate over open and closed arrays in different loops, since you are trying to access private [i], being i = 1,2,3 ... and private does not contain any valid pointers (just a bunch of NULL). This should work (unless I miss something else):

 account* bank_ledger::lookup(double accnum) { for(int i = 0; i < num_open; i++) { if(open[i]->get_account_number() == accnum) return open[i]; } for(int i = 0; i < num_closed; i++) { if(closed[i]->get_account_number() == accnum) return closed[i]; } return 0; } 
+4
source

Source: https://habr.com/ru/post/1400923/


All Articles