Проблема управления памятью в 2d массиве - PullRequest
0 голосов
/ 03 декабря 2018

Мне нужно написать код, который получает строку и превращает ее в объект класса.Все работает, как и ожидалось, но я не могу освободить динамически размещенный 2d массив объектов.

Я знаю, что проблема в деструкторе и операторе присваивания Move для объекта, я продолжаю получать ошибки SIGBRT и EXC_BAD_ACCESS, когда пытаюсь его запустить.

Ниже приведен мой код для конструктора, деструктор и перемещение присваивания / конструктор

//CustomerOrder.cpp
CustomerOrder::CustomerOrder(std::string& 
src):Name(src),Product(),ItemCount(),ItemList(),field_width(){
std::vector<ItemInfo> info;
std::string* tokens[] = { &Name, &Product };
Utilities utils;
size_t next_pos = -1;
bool more = true;

for (auto& i : tokens) {
    if (!more) break;
    *i = utils.extractToken(src, next_pos, more);
}
while (more){
    info.push_back(utils.extractToken(src, next_pos, more));
}
if(!info.empty() && info.back().ItemName.empty()){
    info.pop_back();
}
ItemCount = info.size();


ItemList = new ItemInfo*[ItemCount];
for (int i = 0; i < ItemCount; i++){
    ItemList[i] = new ItemInfo(info.at(i).ItemName);
}
if (utils.getFieldWidth() > field_width){
    field_width = utils.getFieldWidth();
}
}

CustomerOrder::~CustomerOrder(){
for(int i = 0; i<ItemCount;i++){
    delete[] ItemList[i];
}
delete[] ItemList;
}

CustomerOrder::CustomerOrder(CustomerOrder&& src){
*this = std::move(src);
}

CustomerOrder& CustomerOrder::operator=(CustomerOrder&& src){
if(this!= &src){
    delete [] ItemList;
    Name = std::move(src.Name);
    Product = std::move(src.Product);
    ItemCount = std::move(src.ItemCount);
    ItemList = std::move(src.ItemList);
    src.ItemList = nullptr;
}
return *this;
}

И структура ItemInfo

//ItemInfo struct
struct ItemInfo
{
std::string ItemName;
unsigned int SerialNumber;
bool FillState;

ItemInfo(std::string src) : ItemName(src), SerialNumber(0), 
FillState(false) {};
};

Ответы [ 2 ]

0 голосов
/ 03 декабря 2018

Эта строка вашего кода ItemList[i] = new ItemInfo(info.at(i).ItemName); не выделяет динамический массив, но этот код в вашем деструкторе пытается удалить его, как если бы он был динамическим массивом.

for(int i = 0; i<ItemCount;i++){
    delete[] ItemList[i];
}

Быстрым решением было бы изменить delete [] на delete .Однако кажется, что было бы намного проще просто выделить один динамический массив.Другими словами, выделите ItemList как таковой ItemList = new ItemInfo[ItemCount]; Конечно, вам придется изменить тип, но это имеет больше смысла из того, что вы опубликовали.

Другая возможная проблема заключается в том, что в вашем деструкторе вы не проверяетеесли ItemList является nullptr или фактически выделен для чего-либо.На что ваш деструктор может попытаться получить доступ к неверным данным.Кроме того, ваш оператор перемещения удаляет ItemList, не удаляя данные внутри него.

Вы можете создать функцию для освобождения данных в ItemList и затем вызвать эту функцию из деструктора и оператора перемещения.

Кстати, почему вы используете динамические двумерные массивы, когда кажется, что вы знаете, как использовать векторы?Вектор справился бы со всем этим гораздо проще.Например, тип будет std::vector<std::vector<ItemInfo>>.

0 голосов
/ 03 декабря 2018

Вы комбинируете «новое» с «удалить []».Если вы используете «new», используйте «delete», если вы используете «new []», тогда используйте «delete []» для этой вещи.

Это ваша проблема там: «delete [] ItemList [i];"это должно быть "delete ItemList [i];"вместо

...