mardi 3 décembre 2019

new char [] in dynamic constructor throws "corrupted top size";

I have a strange, at least for me, issue with dynamic allocation of char array in constructor.

I have couple of constructors and functions in my class which perform dynamic allocation of char array and only one of them throws "corrupted top size" exception from malloc(); Code is provided below and i have left the comment where exception is thrown. The pointers are simply defined in class definition as "char *_name". All other constructors and functions are checked and are working properly. Any help will be appreciated.

#include "contact.h"
#include <stdexcept>
#include <iostream>

MT::Contact::Contact() :
    _name_length(0),
    _surname_length(0),
    _birth_date_length(0),
    _phone_number_length(0),
    _city_length(0),
    _position_length(0),
    _size(0),
    _name(nullptr),
    _surname(nullptr),
    _birth_date(nullptr),
    _phone_number(nullptr),
    _city(nullptr),
    _position(nullptr),
    _to_file(nullptr),
    _new_contact(true),
    _modified_contact(false)
{

}

MT::Contact::Contact(int8_t *data) :
    _to_file(nullptr)
{
    int start = 0;
    _name_length = *(data+start);
    ++start;
    _surname_length = *(data+start);
    ++start;
    _birth_date_length = *(data+start);
    ++start;
    _phone_number_length = *(data+start);
    ++start;
    _city_length = *(data+start);
    ++start;
    _position_length = *(data+start);
    ++start;
    _name = new char[_name_length];//Here is the exception (and for all other allocations in this constructor)
    strncpy(_name, reinterpret_cast<char *>(data+start), _name_length);
    start += _name_length;
    _surname = new char[_surname_length];
    strncpy(_surname, reinterpret_cast<char *>(data+start), _surname_length);
    start += _surname_length;
    _birth_date = new char[_birth_date_length];
    strncpy(_birth_date, reinterpret_cast<char *>(data+start), _birth_date_length);
    start += _birth_date_length;
    _phone_number = new char[_phone_number_length];
    strncpy(_phone_number, reinterpret_cast<char *>(data+start), _phone_number_length);
    start += _phone_number_length;
    _city = new char[_city_length];
    strncpy(_city, reinterpret_cast<char *>(data+start), _city_length);
    start += _city_length;
    _position = new char[_position_length];
    strncpy(_position, reinterpret_cast<char *>(data+start), _position_length);
    _new_contact = false;
    _modified_contact = false;
}

MT::Contact::Contact(const MT::Contact &other) :
    _name_length(other._name_length),
    _surname_length(other._surname_length),
    _birth_date_length(other._birth_date_length),
    _phone_number_length(other._phone_number_length),
    _city_length(other._city_length),
    _position_length(other._position_length),
    _size(other._size),
    _to_file(nullptr),
    _new_contact(other._new_contact), _modified_contact(other._modified_contact)
{
    _name = new char[_name_length];
    strcpy(_name, other._name);
    _surname = new char[_surname_length];
    strcpy(_surname, other._surname);
    _birth_date = new char[_birth_date_length];
    strcpy(_birth_date, other._birth_date);
    _phone_number = new char[_phone_number_length];
    strcpy(_phone_number, other._phone_number);
    _city = new char[_city_length];
    strcpy(_city, other._city);
    _position = new char[_position_length];
    strcpy(_position, other._position);
}

MT::Contact::Contact(MT::Contact &&other):
    _name_length(other._name_length),
    _surname_length(other._surname_length),
    _birth_date_length(other._birth_date_length),
    _phone_number_length(other._phone_number_length),
    _city_length(other._city_length),
    _position_length(other._position_length),
    _size(other._size),
    _to_file(nullptr),
    _new_contact(other._new_contact), _modified_contact(other._modified_contact)
{
    _name = other._name;
    _surname = other._surname;
    _birth_date = other._birth_date;
    _phone_number = other._phone_number;
    _city = other._city;
    _position = other._position;
    other._size = 0;
    other._name_length = 0;
    other._birth_date_length = 0;
    other._phone_number_length = 0;
    other._surname_length = 0;
    other._city_length = 0;
    other._position_length = 0;
    other._name = nullptr;
    other._surname = nullptr;
    other._birth_date = nullptr;
    other._phone_number = nullptr;
    other._city = nullptr;
    other._position = nullptr;
    other._to_file = nullptr;
}

MT::Contact &MT::Contact::operator=(const MT::Contact &other)
{
    if (this != &other){
        if (_name != nullptr){
            delete [] _name;
        }
        if (_surname != nullptr){
            delete [] _surname;
        }
        if (_birth_date != nullptr){
            delete [] _birth_date;
        }
        if (_phone_number != nullptr){
            delete [] _phone_number;
        }
        if (_city != nullptr){
            delete [] _city;
        }
        if (_position != nullptr){
            delete [] _position;
        }
        _name_length = other._name_length;
        _surname_length = other._surname_length;
        _birth_date_length = other._birth_date_length;
        _phone_number_length = other._phone_number_length;
        _city_length = other._city_length;
        _position_length = other._position_length;
        _size = other._size;
        _name = new char[_name_length];
        strcpy(_name, other._name);
        _surname = new char[_surname_length];
        strcpy(_surname, other._surname);
        _birth_date = new char[_birth_date_length];
        strcpy(_birth_date, other._birth_date);
        _phone_number = new char[_phone_number_length];
        strcpy(_phone_number, other._phone_number);
        _city = new char[_city_length];
        strcpy(_city, other._city);
        _position = new char[_position_length];
        strcpy(_position, other._position);
        _new_contact = other._new_contact;
        _modified_contact = other._modified_contact;
    }
    return *this;
}

MT::Contact &MT::Contact::operator=(MT::Contact &&other)
{
    if (this != &other){
        if (_name != nullptr){
            delete [] _name;
        }
        if (_surname != nullptr){
            delete [] _surname;
        }
        if (_birth_date != nullptr){
            delete [] _birth_date;
        }
        if (_phone_number != nullptr){
            delete [] _phone_number;
        }
        if (_city != nullptr){
            delete [] _city;
        }
        if (_position != nullptr){
            delete [] _position;
        }
        _name_length = other._name_length;
        _surname_length = other._surname_length;
        _birth_date_length = other._birth_date_length;
        _phone_number_length = other._phone_number_length;
        _city_length = other._city_length;
        _position_length = other._position_length;
        _size = other._size;
        _name = other._name;
        _surname = other._surname;
        _birth_date = other._birth_date;
        _phone_number = other._phone_number;
        _city = other._city;
        _position = other._position;
        _new_contact = other._new_contact;
        _modified_contact = other._modified_contact;
        other._size = 0;
        other._name_length = 0;
        other._surname_length = 0;
        other._city_length = 0;
        other._position_length = 0;
        other._name = nullptr;
        other._surname = nullptr;
        other._birth_date = nullptr;
        other._phone_number = nullptr;
        other._city = nullptr;
        other._position = nullptr;
        other._to_file = nullptr;
        std::cout << "Move" << std::endl;
    }

    return *this;
}

void MT::Contact::set_name(const char *name)
{
    if (name == nullptr || strcmp(name, "") == 0){
        throw std::invalid_argument("void MT::Contact::set_name(const char *name): empty [name] was provided");
    }
    _name_length = strlen(name);
    if (!_new_contact){
        delete [] _name;
        _modified_contact = true;
    }
    _name = new char[_name_length];
    strcpy(_name, name);
    _size += _name_length;
}

void MT::Contact::set_surname(const char *surname)
{
    if (surname != nullptr && strcmp(surname, "") != 0){
        _surname_length = strlen(surname);
        if (!_new_contact){
            delete [] _surname;
            _modified_contact = true;
        }
        _surname = new char[_surname_length];
        strcpy(_surname, surname);
        _size += _surname_length;
    }
}

void MT::Contact::set_birthdate(const char *birth_date)
{
    if (birth_date != nullptr && strcmp(birth_date, "") != 0){
        _birth_date_length = strlen(birth_date);
        if (!_new_contact){
            delete [] _birth_date;
            _modified_contact = true;
        }
        _birth_date = new char[_birth_date_length];
        strcpy(_birth_date, birth_date);
        _size += _birth_date_length;
    }
}

void MT::Contact::set_phone_number(const char *phone_number)
{
    if (phone_number != nullptr && strcmp(phone_number, "") != 0){
        _phone_number_length = strlen(phone_number);
        if (!_new_contact){
            delete [] _phone_number;
            _modified_contact = true;
        }
        _phone_number = new char[_phone_number_length];
        strcpy(_phone_number, phone_number);
        _size += _phone_number_length;
    }
}

void MT::Contact::set_city(const char *city)
{
    if (city != nullptr && strcmp(city, "")  != 0){
        _city_length = strlen(city);
        if (!_new_contact){
            delete [] _city;
            _modified_contact = true;
        }
        _city = new char[_city_length];
        strcpy(_city, city);
        _size += _city_length;
    }
}

void MT::Contact::set_position(const char *position)
{
    if (position != nullptr && strcmp(position, "") != 0){
        _position_length = strlen(position);
        if (!_new_contact){
            delete [] _position;
            _modified_contact = true;
        }
        _position = new char[_position_length];
        strcpy(_position, position);
        _size += _position_length;
    }
}

int MT::Contact::size() const
{
    return _size;
}

const char *MT::Contact::name() const
{
    return _name;
}

const char *MT::Contact::surname() const
{
    if (_surname == nullptr){
        return "";
    }
    return _surname;
}

const char *MT::Contact::birth_date() const
{
    if (_birth_date == nullptr){
        return "";
    }
    return _birth_date;
}

const char *MT::Contact::phone_number() const
{
    if (_phone_number == nullptr){
        return "";
    }
    return _phone_number;
}

const char *MT::Contact::city() const
{
    if (_city == nullptr){
        return "";
    }
    return _city;
}

const char *MT::Contact::position() const
{
    if (_position == nullptr){
        return "";
    }
    return _position;
}

bool MT::Contact::is_new() const
{
    return _new_contact;
}

bool MT::Contact::is_modified() const
{
    return _modified_contact;
}

int8_t *MT::Contact::to_file()
{
    if (_to_file != nullptr){
        delete [] _to_file;
    }
    _to_file = new int8_t[_size];
    _to_file[0] = static_cast<int8_t>(_size);
    _to_file[1] = static_cast<int8_t>(_size >> 8);
    _to_file[2] = _name_length;
    _to_file[3] = _surname_length;
    _to_file[4] = _birth_date_length;
    _to_file[5] = _phone_number_length;
    _to_file[6] = _city_length;
    _to_file[7] = _position_length;
    int start = 8;
    memcpy(_to_file+start, _name, _name_length);
    start += _name_length;
    memcpy(_to_file+start, _surname, _surname_length);
    start += _surname_length;
    memcpy(_to_file+start, _birth_date, _birth_date_length);
    start += _birth_date_length;
    memcpy(_to_file+start, _phone_number, _phone_number_length);
    start += _phone_number_length;
    memcpy(_to_file+start, _city, _city_length);
    start += _city_length;
    memcpy(_to_file+start, _position, _position_length);

    return _to_file;
}

MT::Contact::~Contact()
{
    if (_name != nullptr){
        delete [] _name;
    }
    if (_surname != nullptr){
        delete [] _surname;
    }
    if (_birth_date != nullptr){
        delete [] _birth_date;
    }
    if (_phone_number != nullptr){
        delete [] _phone_number;
    }
    if (_city != nullptr){
        delete [] _city;
    }
    if (_position != nullptr){
        delete [] _position;
    }
    if (_to_file != nullptr){
        delete [] _to_file;
    }
}

...

Aucun commentaire:

Enregistrer un commentaire