多次随机向量后的读取访问冲突

Read access violation after shuffling vector multiple times

本文关键字:读取 访问冲突 向量 随机      更新时间:2023-10-16

对于学校项目,我需要用独特的指针打乱向量。但是,当我这样做时,一段时间后出现读取访问冲突错误。我创建向量,然后调用洗牌。这个我做了很多次。我只是用值创建向量并对其进行一次洗牌,几次后我收到读取访问冲突错误。

法典

    int RandomEngine::generateRandomInt(int minValue, int maxValue)
    {
        std::uniform_int_distribution<int> distribution(minValue, maxValue);
        std::cout << "Random getal van " << minValue << " tot " << maxValue << std::endl;
        return distribution(def_rand_engine);
    }
    void RandomEngine::shuffleCharacterCards(std::vector<std::unique_ptr<CharacterCard>>& cards)
    {
        // Succeeds once but with multiple swaps read access violation
        //auto randomInt = generateRandomInt(0, cards.size() - 1);
        //iter_swap(cards.begin() + randomInt, cards.begin());
        // Read access violation
        //for (int i = 0; i < cards.size(); i++)
        //{
        //  std::swap(cards[i], cards[std::rand() % cards.size()]);
        //}
        // Read access violation
        //std::shuffle(cards.begin(), cards.end(), std::mt19937{ def_rand_engine});
        // Read access violation
        //std::random_shuffle(cards.begin(), cards.end());

    // Read access violation
    //std::shuffle(cards.begin(), cards.end(), std::mt19937(std::random_device()()));
}

我从静态类调用洗牌的其他类

void CharacterCardStack::prepare()
{
    std::cout << "Preparing CharacterCardStack..." << std::endl;
    if(cards_.size() > 2)
    {
        // Shuffle the cards
        RandomEngine::shuffleCharacterCards(cards_);
        // Burn the first card
        burnedCharacterCard_ = std::move(cards_[0]);
        std::cout << "Burned charactercard: " << burnedCharacterCard_->getName() << std::endl;
        cards_.erase(cards_.begin());
        // Als de open kaart een koning is dan moet deze vervangen worden door een ander.
        if(cards_[0]->getName() == "Koning")
        {
            turnedCharacterCard_ = std::move(cards_[1]);
        }
        else
        {
            turnedCharacterCard_ = std::move(cards_[0]);
        }
        std::cout << "Turned charactercard: " << turnedCharacterCard_->getName() << std::endl;
        cards_.erase(cards_.begin());
    }
    else
    {
        std::cerr << "CharacterCardStack::prepare cards size is " << cards_.size() << std::endl;
        throw std::exception("Error...");
    }
    for (const auto& c : cards_)
    {
        std::cout << "Other card: " << c->getName() << std::endl;
    }
    std::cout << "CharacterCardStack prepared" << std::endl;
}

你的逻辑中有流,你根据条件移出第一个或第二个元素:

    if(cards_[0]->getName() == "Koning")
    {
        turnedCharacterCard_ = std::move(cards_[1]);
    }
    else
    {
        turnedCharacterCard_ = std::move(cards_[0]);
    }

但随后无条件地擦除第一个元素:

cards_.erase(cards_.begin());

因此,您最终可能会得到移出的指针。

简单的修复可能是:

    if(cards_[0]->getName() == "Koning")
    {
        std::swap( cards_[0], cards_[1] );
    }
    turnedCharacterCard_ = std::move(cards_[0]);
    std::cout << "Turned charactercard: " << turnedCharacterCard_->getName() << std::endl;
    cards_.erase(cards_.begin());

这样更容易保持正确,我更喜欢使用 cards.front() 而不是 cards_[0] ,我认为在这种情况下更具可读性。