2012-03-12 15 views
4

申し訳ありませんが、これはスタックオーバーフローの午前中のsegフォールトポストであることがわかりましたが、このコードを修正するために数日間試してみましたが、困惑しています。みんな私はあなたが助けることを願っています、私は割り当てに従って、とにかくaccount.hファイルを変更許可されていないよStrange Segフォルト

account.h(注:)

とにかく、私はこのコードで奇妙なセグメンテーション違反を取得しています。

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() << "'s 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のとGDBの両方が*(開くには、[i]は)初期化されていないことを言います。ここで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 

それはbankledger::lookupに、メインからbankledgrer::close_accountに行くと、それは私が右、その行の前にcout << *(open[i])を固執した場合、それがうまくそれをプリントアウトしif(open[i]->get_account_number() == accnum)

でクラッシュします。 私は迷っています。どんな助けもありがとう。ヘッダーファイルを含めるか、何かを明確にしたい場合は、私に知らせてください。

PS。また、私はこのコードが非常にCであることを知っていますが、それは私の教授がC++クラスであってもそれを望む方法です。 Go figure。 :\この方法では

+1

+1 for valgrind! – pyCthon

+0

エラーは確定的ですか? – pg1989

+1

'account.h'と' bank_ledger.h'には何がありますか?あなたのコンストラクタはすべてを正しく初期化しましたか?アカウント番号に 'double'と' size_t'を使うことがあるのはなぜですか? –

答えて

4

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; 
     } 
    } 
} 

開いているアカウントの量よりも閉じたアカウントの少なくとも同量があると仮定しています。閉じた[i]、つまりi = 1,2,3 ...にアクセスしようとしているので、別のループで開いた配列と閉じた配列を繰り返し処理する必要があります。また、closedには有効なポインタ( NULLポインター)。これはうまくいくはずです(他に何かがない場合を除いて):

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; 
} 
+0

ありがとう!それはそれをした!私の元のコードはopen [i] - > get_account_number()== accnumでクラッシュしていましたが、これは修正されたようです。それが問題であった閉鎖索引だったのなら、なぜそれがオープン[i] - >セグメンテーションを引き起こしていたのか知​​っていますか? – vanchagreen

+0

私は知らない:/。私はそれを理解しようとしているが、理にかなっていない。それは、クローズド[i] nullポインタ - 参照解除時にクラッシュするはずです。奇妙な... – mfontanini

+0

たぶんそれは、コンパイラ/ valgrindちょうどそれが間違っていますか? – vanchagreen

関連する問題