'std :: bad_alloc' при попытке удалить элементы priority_queue C ++ - PullRequest
0 голосов
/ 20 мая 2019

При возврате судна в порт скорость становится равной 0,0, а пользователь вводит щит и топливо.

- если топливо равно 0.0, корабль уничтожается

- Корабли, все еще находящиеся в очереди priority_que, получают 10 урона щитом и теряют 15 единиц топлива

- если щит или топливо становятся меньше 0,0, корабль уничтожается

Попытка реализовать эти инструкции для моего окончательного проекта. Корабли относятся к типу указателей и находятся в приоритетной очереди с именем «Поле битвы». Корабли также существуют в списке указателей, называемых «порт». Я пытаюсь уничтожить корабли, которые получают смертельные повреждения, но когда я пытаюсь их показать, программа Qt падает, и я получаю ошибку bad_alloc. Это последнее, что я должен сделать для своего проекта: (

Важные блоки кода из различных файлов:

Я уже пытался удалить корабли из порта, а также пытался напрямую удалить их из порта, но приоритет_квартиры испортился.

class Civilization {
string name;
int x;
int y;
list<Villager> villagers;
list<Ship*> port;
priority_queue<Ship*, vector<Ship*>, Ship::comp> battle;
}


void Civilization::damageShips()
{
priority_queue<Ship*, vector<Ship*>, Ship::comp> copy = battle;
Ship *s = battle.top();
s->setSpeed(0.0);

while(!copy.empty()) {
    Ship *s = copy.top();
    s->setShield(s->getShield() - 10);
    s->setFuel(s->getFuel() - 15);
    copy.pop();
}


priority_queue<Ship*, vector<Ship*>, Ship::comp> temp;

while(!copy.empty()) {
    Ship *s = copy.top();
    string id = s->getId();

    if (s->getShield() > 0 && s->getFuel() > 0) {
        temp.push(s);
    } else
        deleteShip(id);
    copy.pop();
}


battle = temp;
battle.pop();
}

void battlefielddisplay::setCivilization(Civilization *civilizaition)
{
size_t size = civilizaition->battlefieldSize();
ui->battlefield_table->setRowCount(int(size));

Civilization &c = *civilizaition;

priority_queue<Ship*, vector<Ship*>, Ship::comp> copy = c.getBattlefield();

int cnt = 0;
while(!copy.empty()) {
    Ship *s = copy.top();

    QString id = QString::fromStdString(s->getId());
    QString fuel = QString::number(s->getFuel());
    QString speed = QString::number(s->getSpeed());
    QString shield = QString::number(s->getShield());
    QString warriors = QString::number(s->size());

    QTableWidgetItem *idItem = new QTableWidgetItem(id);
    QTableWidgetItem *fuelItem = new QTableWidgetItem(fuel);
    QTableWidgetItem *speedItem = new QTableWidgetItem(speed);
    QTableWidgetItem *shieldItem = new QTableWidgetItem(shield);
    QTableWidgetItem *warriorsItem = new QTableWidgetItem(warriors);

    ui->battlefield_table->setItem(cnt, 0, idItem);
    ui->battlefield_table->setItem(cnt, 1, fuelItem);
    ui->battlefield_table->setItem(cnt, 2, speedItem);
    ui->battlefield_table->setItem(cnt, 3, shieldItem);
    ui->battlefield_table->setItem(cnt, 4, warriorsItem);

    cnt++;

    copy.pop();
}

}

void MainWindow::on_battle_remove_ship_clicked()
{
if (flag) {
    Civilization* c = videogame.searchCivilization(ui->civilization_search_input->text().toStdString());

    double shield = ui->shield_battle_remove->value();
    double fuel = ui->fuel_battle_remove->value();

    Ship *s = c->getBattleShip();
    s->setSpeed(0.0);
    s->setShield(shield);
    s->setFuel(fuel);

    c->damageShips();

    qDebug() << "[✔]" << "Removed ship from battlefield";

} else
    QMessageBox::information(this, "Error", "Civilization not found");
}

bool Civilization::deleteShip(string &id)
{
bool found = false;
for(size_t i(0); i < shipSize(); ++i) {
    auto it = port.begin();
    advance(it, i);
    auto x = *it;
    if (x->getId() == id) {
        port.erase(it);
        delete x;
        --i;
        found = true;
    }
}
return found;
}

1 Ответ

0 голосов
/ 20 мая 2019

Основная проблема, которую я вижу, состоит в том, что вы удаляете объекты, не удаляя указатели из контейнера.Вы повторяете один и тот же контейнер несколько раз и пытаетесь получить доступ к удаленным объектам.

Дополнительная проблема заключается в том, что у вас есть несколько копий одной и той же очереди, поэтому даже удаление указателя из основного контейнера может вызвать проблемы.

Попробуйте пересмотреть алгоритм, обращая особое внимание на время жизни объектов.Например, у вас может быть отложенное удаление: вместо удаления просто пометьте объекты как те, которые будут удалены позже.У вас может быть очистка в конце вашей функции.

...