Ошибка сегментации: 11 и ошибки malloc в коде C ++ - PullRequest
0 голосов
/ 04 марта 2012

Хорошо, я знаю, что в этом коде, вероятно, много ошибок. Я довольно новичок в динамическом распределении памяти, указателях и т. Д.

Заголовочный файл account.h предоставлен нам нашим профессором. Нам сказали не вносить никаких изменений в файл .h.

Файл реализации написан мной. Основная функция включена только для базового начального тестирования. Нам дали еще один файл для проверки реализации класса account.

Если я не закомментирую строку имени cout, я получаю ошибку seg error 11. Если я это сделаю, он напечатает номер счета, но выдает эту ошибку:

Тест (29976) malloc: * ошибка для объекта 0x62c1aa18c9d8374: освобожденный указатель не был выделен * установить точку останова в malloc_error_break для отладки
Ловушка отмены: 6

Любая помощь будет принята с благодарностью!

Вот заголовочный файл:

class account
{
public:
    typedef char* string;
    static const size_t MAX_NAME_SIZE = 15;
    // CONSTRUCTOR
    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 ostream& operator <<(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
};

Вот файл реализации:

// File: account.cxx
// Author: Mike Travis
// Last Modified: Mar 3, 2012
// Description: implementation of Account class as prescribed by the file account.h

#include <cstdlib>
#include <stdio.h>
#include <iostream>
#include "account.h"

using namespace std;

//Constructor

account::account(char* i_name, size_t i_acnum, size_t i_hsize){
    string *d_history;
    d_history = new string[i_hsize];

    for(int i = 0; i<i_hsize; i++){
        name[i] = i_name[i];
    }
    ac_number = i_acnum;
    history_size = i_hsize;
    history_count = 0; 
}


account::account(const account& ac){
    string *d_history;
    d_history = new string[ac.history_size];

    for( int i=0; i<ac.get_current_history_size(); i++){
        strcpy(d_history[i], history[i]);
    }

    strcpy(name,ac.get_name());
    ac_number = ac.get_account_number();
    history_size = ac.get_max_history_size();
    history_count = ac.get_current_history_size();
}

account::~account(){    delete [] history;  }

void account::set_name(char* new_name){                 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){
    strcpy(history[history_count], new_history);
    history_count++;
}

char* account::get_name() const {
    char* name_cpy;
    strcpy(name_cpy, name);
    return name_cpy;
}

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;   }
//string* account::get_history() const{                         return *history;        }


int main(){

    account test1("mike travis", 12345, 20);
    //cout<<"\nname: "<< test1.get_name();

    cout<<"\n\nacnum: "<<test1.get_account_number()<<"\n\n";

    return 0;
}

Ответы [ 2 ]

1 голос
/ 04 марта 2012

В деструкторе account вы удаляете массив history. Однако в конструкторе вы выделяете (и пропускаете) массив, который хранится в локальной переменной d_history. Предположительно, вы хотели присвоить это переменной-члену history вместо этого - поскольку вы этого не сделали, если вы дойдете до деструктора, он выдаст вам сообщение о том, что вы освобождаете history, но никогда не выделяли его.

Существует аналогичная ошибка и в конструкторе копирования.

Есть и другие ошибки в вашем коде, которые, я полагаю, вы обнаружите по ходу дела, например, get_name() не будет работать. Я подозреваю, что заголовочный файл здесь не помогает, но ничего не поделаешь, если вы не должны это менять.

0 голосов
/ 04 марта 2012

Я написал немного кода для вас и исправил эпические ошибки (даже в заголовочном файле, извините;)). Это все еще очень уродливо и непристойно, но, может быть, вы можете узнать что-то, прочитав это:

#include <cstddef>
#include <ostream>

class account
{
    // The whole class makes no sense, since it has no useful
    // member function or anything like this.
    // Furthermore, the class provides almost full access to all its member variables.
    // At this point one could just make everything public.

    // This is not even exception safe when the constructor throws.
    // A good implementation would use history_entry and history classes, 
    // together with std::string and std::vector/std::deque
    // And it would provide some sort of functionality. ;)

public:
  account(const char* name, unsigned number, std::size_t history_max_size);
  account(const account& other);
  ~account();

    const char* name() const;
  unsigned number() const;
  double balance() const;
    const char* const* history() const;
    std::size_t history_size() const;
  unsigned history_max_size() const;

  void set_name(const char* new_name);
  void set_number(unsigned new_number);
  void set_balance(double new_balance);
  void add_history(const char* new_history);

private:
  char* name_;
  unsigned number_;
  double balance_;
  char** history_;
    std::size_t history_size_;
    const std::size_t history_max_size_;
};

std::ostream& operator << (std::ostream& stream, const account& a);


#include <cassert>
#include <cstring>

account::account(const char* name, unsigned number, std::size_t history_max_size)
    : name_(0)
    , number_(number)
    , balance_(0.0)
    , history_(new char*[history_max_size])
    , history_size_(0)
    , history_max_size_(history_max_size)
{
    assert(name != 0);
    assert(history_max_size != 0);
    set_name(name);
}

account::account(const account& other)
    : name_(0)
    , number_(other.number_)
    , balance_(other.balance_)
    , history_(new char*[other.history_max_size_])
    , history_size_(other.history_size_)
    , history_max_size_(other.history_max_size_)
{
    set_name(other.name_);
    for (std::size_t i = 0; i != other.history_size_; ++i)
    {
        history_[i] = new char[std::strlen(other.history_[i]) + 1];
        strcpy(history_[i], other.history_[i]);
    }
}

account::~account()
{
    delete[] name_;

    for (std::size_t i = 0; i != history_size_; ++i)
        delete[] history_[i];
    delete[] history_;
}

const char* account::name() const
{
    return name_;
}

unsigned account::number() const
{
    return number_;
}

double account::balance() const
{
    return balance_;
}

const char* const* account::history() const
{
    return history_;
}

std::size_t account::history_size() const
{
    return history_size_;
}

unsigned account::history_max_size() const
{
    return history_max_size_;
}

void account::set_name(const char* new_name)
{
    if (name_)
        delete[] name_;

    name_ = new char[std::strlen(new_name) + 1];
    std::strcpy(name_, new_name);
}

void account::set_number(unsigned new_number)
{
    number_ = new_number;
}

void account::set_balance(double new_balance)
{
    balance_ = new_balance;
}

void account::add_history(const char* new_history)
{
    if (history_size_ == history_max_size_)
    {
        delete[] history_[0]; // delete oldest entry
        for (std::size_t i = 0; i != history_size_ - 1; ++i)
            history_[i] = history_[i + 1];
        --history_size_;
    }

    history_[history_size_] = new char[strlen(new_history) + 1];
    std::strcpy(history_[history_size_], new_history);
    ++history_size_;
}

std::ostream& operator << (std::ostream& stream, const account& a)
{
    return stream << "account [name: " << a.name() << ", number: " 
        << a.number() << ", balance: " << a.balance() << ']';
}


#include <iostream>

int main()
{
    account a("Hello!", 500, 5);
    a.set_balance(12.546);
    for (int i = 50; i--; )
        a.add_history("Yaaay..");
    //account b = a;
    std::cout << a << '\n';
}
...