Проблемы с выделением памяти при работе с new char

Пишу класс для работы с большими числами

Само число храню как массив char

class BigInt {
private:
    bool is_positive;
    bool is_set;
    size_t size;
    char* number;

Мне нужен конструктор считывания числа из строки

Код конструктора:

BigInt::BigInt(const string& str)
{
    size_t pos = str.find_first_not_of("-0");
    if (str == "") {
        this->number = nullptr;
        this->is_positive = true;
        this->is_set = false;
        this->size = 0;
    }
    else if (pos == string::npos) {
        this->size = 1;
        this->number = new char[1];
        this->is_set = true;
        this->is_positive = true;
        this->number[0] = '0';
    }
    else if(str.length() > pos)
    {
        if (str[0] == '-')
            this->is_positive = false;
        else
            this->is_positive = true;
        this->size = str.length() - pos;
        cout << " size " << this->size << " " << pos <<" pos"<< endl;
        this->number = new char[this->size];
        for (size_t i = 0; i < size; i++) {
           this->number[i] = str[pos + i];
        }
        this->is_set = true;
    } 
    else {
        this->number = nullptr;
        this->is_positive = true;
        this->is_set = false;
        this->size = 0;
    }
}

однако здесь в строчке

this->number = new char[this->size] 

возникает проблема с памятью:
(Detected memory leaks! Dumping objects ->{272} normal block at 0x011FFC88, 30 bytes long. Data: <1234567890123456> 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 )

Для того, чтобы не учитывать знак и незначащие нули, учитываю первую позицию не этих символов

Никак не могу понять, что здесь не так :(

P.S.

Ниже конструкторы копирования и операторы присвоения и деструтктор


BigInt::BigInt(const BigInt& n)//копирование
    : is_positive(n.is_positive)
    , size(n.size)
    , is_set(n.is_set)
{
    if (n.is_set) {
        this->number = new char[size];
        for (size_t i = 0; i < size; i++) {
            this->number[i] = n.number[i];
        }
 
    }
    else
        this->number = nullptr;
}

BigInt::BigInt(BigInt&& other)//перемещения
    : size(move(other.size))
    , number(other.number)
    , is_positive(move(other.is_positive))
    , is_set(move(other.is_set))
{
    other.number = nullptr;
    other.size = 0;
    other.is_positive = true;
    other.is_set = false;
}
BigInt::~BigInt()//деструктор
{
    if (this->is_set) {
        delete [] this->number;
        this->size = 0;
        this->is_positive = true;
        this->number = nullptr;
        this->is_set = false;
    }
}
BigInt& BigInt::operator=(const BigInt& other)//присвоения
{
    if (this == &other) {
        return *this;
    }
    if (this->is_set) {
        delete[] this->number;
        this->size = 0;
        this->is_positive = true;
        this->number = nullptr;
        this->is_set = false;
    }
    if (other.is_set) {
        this->size = other.size;
        this->is_positive = other.is_positive;
        this->number = new char[this->size];
        for (size_t i = 0; i < this->size; i++) {
            this->number[i] = other.number[i];
        }
        this->is_set = true;
    }
    return *this;
}
BigInt& BigInt::operator=(const int intn1)//присваивание для int 
{
    BigInt other(to_string(intn1));
    *this = other;
    return *this;
}
BigInt& BigInt::operator=(BigInt&& moved)//перемещающий
{
    if (this == &moved) {
        return *this;
    }
    if (this->is_set) {
        delete[] this->number; //удаляем высвобожденную память под обьект
        this->size = 0;
        this->is_positive = true;
        this->number = nullptr;
        this->is_set = false;
    }
    if (moved.is_set) {
        size = move(moved.size);
        number = moved.number; //перемещаем указатель на нужную память
        is_set = move(moved.is_set);
        is_positive = move(moved.is_positive);
        moved.number = nullptr;
        moved.size = 0;
        moved.is_set = false;
        moved.is_positive = true;
    }
    return *this;
}

Ответы (1 шт):

Автор решения: wololo

А вы уверены, что правильно используете инструменты для обнаружения утечек?

Воспользуемся Visual Studio и CRT library (docs.microsoft.com, habr.com), и напишем следующий тестовый код:

#include <iostream>

#ifdef _DEBUG
#include <crtdbg.h>
#define _CRTDBG_MAP_ALLOC
#endif

class test
{
public:
    test()
    {
        std::cout << "test.constructor" << std::endl;
        int size = 10;
        buff = new char[size];
        for (int i = 0; i < size; ++i)
            buff[i] = 'a' + i;
    }
    ~test()
    {
        std::cout << "test.destructor" << std::endl;
        delete [] buff;
    }
 
private:
    char* buff;
};

int main()
{
    _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE );
    _CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDOUT );
    {
        test t;
        //_CrtDumpMemoryLeaks();
    } //Здесь будет вызван деструктор test.
    _CrtDumpMemoryLeaks();
}

Приведённый код у меня выводит:

test.constructor
test.destructor

Но стоит только раскомментировать строку //_CrtDumpMemoryLeaks();, как вывод сразу станет таким:

test.constructor
Detected memory leaks!
Dumping objects ->
{125} normal block at 0x00345E68, 10 bytes long.
 Data: <abcdefghij> 61 62 63 64 65 66 67 68 69 6A 
Object dump complete.
test.destructor

Раскомментированная функция _CrtDumpMemoryLeaks сообщает, что есть неосвобождённая память, и это правда, ведь деструктор класса test ещё не был вызван.

Убедитесь, что наличие утечек вы проверяете после того, как будут вызваны все деструкторы вашего класса.

Если вы создаёте экземпляр вашего класса непосредственно в функции main:

int main(){
    BigInt b("12345");
    ...
}

то деструктор будет вызван при завершении работы функции main.

→ Ссылка