簡體   English   中英

引發異常:讀取訪問沖突[C ++]

[英]Exception thrown: read access violation [C++]

你好 我目前正在學習編程,因此暫時不清理代碼,我需要幫助來使代碼首先運行。 另外,我對大量的代碼塊表示歉意。 我不知道這是否與問題無關,所以無論如何我都將其發布了。

我們當前的課程是在課堂上,我正在嘗試讓2個向導互相對決。 但是在此之前,我需要為兩個向導的屬性分配值:

class Spell
{
public:
    string name;
    unsigned int cost;
    unsigned int dmg;
};

class Wizard
{
public:
    string name;
    unsigned int hp;
    unsigned int mp;
    Spell* spell;
};


void assignWizardValues(Wizard* wizard, Spell* spell)
{
    wizard->hp = rand() % 25 + 76;
    wizard->mp = rand() % 25 + 76;
    spell->name = "Fireball";
    spell->cost = rand() % 10 + 6;
    spell->dmg = rand() % 10 + 6;
}

在我的main()中,我有這個:

int main()
{
    Wizard* wiz1 = new Wizard();
    Wizard* wiz2 = new Wizard();
    Spell* fireball1 = new Spell();
    Spell* fireball2 = new Spell();

    //Assign Property Values
    srand(time(NULL)); 

    cout << "Who is the first wizard?  ";
    cin >> wiz1->name;
    assignWizardValues(wiz1, fireball1);

    cout << "Who is the second Wizard?  ";
    cin >> wiz2->name;
    assignWizardValues(wiz2, fireball2);

    //Battle START!!

    while (canGoOn(wiz1) == true && canGoOn(wiz2) == true)
    {
        castSpell(wiz1, wiz2);
        castSpell(wiz2, wiz1);
    }

    system("pause");
    return 0;
}

為兩個向導和兩個咒語分配值都可以。 然后,當它進入戰斗循環時,會彈出此錯誤:

Exception thrown: read access violation.
std::_String_alloc<std::_String_base_types<char,std::allocator<char> > 
>::_Get_data(...) returned nullptr.

這就是我目前所處的位置。 作為參考,這是我在該循環中可以使用的其他兩個函數:

void castSpell(Wizard* caster, Wizard* enemy)
{
    cout << caster->spell->name << endl;
    caster->mp -= caster->spell->cost;
    enemy->hp -= caster->spell->dmg;
    cout << caster->hp << endl << caster->mp << endl << endl;
    cout << enemy->hp << endl << enemy->mp << endl << endl;
    cout << endl << endl;
}

bool canGoOn(Wizard* wizard)
{
    if (wizard->hp > 0 && wizard->mp > 0)
    {
        return true;
    }
    else
    {
        return false;
    }
}

任何幫助將不勝感激,再次,我很抱歉代碼轉儲,很抱歉代碼不好,很抱歉,這篇文章很長。 我在繩子的盡頭TbT

導致崩潰的問題是您沒有在任何地方將法術分配給向導,因此指針默認初始化為空指針。 現在,您castSpellcastSpell函數中取消引用此空指針,以嘗試訪問無效的內存(未定義的行為)。

最好的是已經在構造函數中分配了該拼寫,因此您永遠不會陷入具有無效值的情況。 您可以通過多種方式來做到這一點:

Wizard(std::string name)
    : name(std::move(name)), // std::move: avoids unnecessary copying of data...
      hp(rand() % 25 + 76),
      mp(rand() % 25 + 76),
      spell(new Spell("Fireball"))
      // assuming Spell has a constructor similar to this one
{ }

變體:

Wizard
(
    std::string name, unsigned int hp, unsigned int mp,
    std::string spellName, unsigned int spellCost, unsigned int spellDamage
)
    : name(std::move(name)),
      hp(hp), mp(mp),
      spell(new Spell(std::move(spellName), spellCost, spellDamage))
      // same assumption...
{ }

現在,您可以定義所有已經在外部的參數,然后將它們傳入(現在有許多參數,但是更具靈活性)。

好的,現在還有很多話要說:內存泄漏(您不刪除使用new創建的對象),智能指針(讓刪除自動完成),移動語義(關於std::move含義是什么?)現在,您可能會忽略它……),封裝(您的成員是公共的,應該是私有的),成員函數(以便您可以訪問私有成員),內聯與否以及隱藏實現細節(將代碼拆分為標頭)和來源),...

假設您剛開始學習時,稍后再進行所有操作(但是,如果有興趣,請發表評論,我會發布更多內容...)。 只是樣式問題:請勿將布爾值與true或false進行比較,只需直接使用條件即可:

while (canGoOn(wiz1) == true && canGoOn(wiz2) == false) // bad style
//                                               ^^^^^
// changed just for demonstration purposes!

while (canGoOn(wiz1) && !canGoOn(wiz2))  // the way to go.
//                      ^ to check if condition is NOT met...
//                        again for demonstration only, not in your REAL code!

與返回值類似,如果仍要計算布爾值,則直接將其返回:

bool canGoOn(Wizard* wizard)
{
    return wizard->hp > 0 && wizard->mp > 0; // just drop that if/else stuff around
}

這是我想到的。

當它們都在死亡前耗盡魔法時無限循環;)但是您可以修復它

#include<random>
std::random_device rd;  //Will be used to obtain a seed for the random number engine
std::mt19937 gen(rd()); //Standard mersenne_twister_engine seeded with rd()

int ThrowDie(int dieSize)
{
    std::uniform_int_distribution<> dis(1, dieSize);
    return dis(gen);
}

#include <string>
#include <utility>
class Spell {
    const int cost_base;
    const int cost_die;
    const int damage_base;
    const int damage_die;
public:
    const std::string name;

    Spell(const std::string& name, int cost_base, int cost_die,
        int damage_base, int damage_die)
        : name(name), cost_base(cost_base), cost_die(cost_die)
        , damage_base(damage_base), damage_die(damage_die) {}
    virtual ~Spell() = default;
    // returns <cost, damage>
    std::pair<int, int> Cast();
};

std::pair<int, int> Spell::Cast()
{
    return std::make_pair(
        cost_base + ThrowDie(cost_die),
        damage_base + ThrowDie(damage_die)
    );
}

class Fireball : public Spell {
public:
    Fireball() : Spell("FireBall", 6, 10, 6, 10) {}
    using Spell::Cast;
};

class Wizard
{
public:
    Wizard(const std::string& name);
    void cast(Spell spell, Wizard& opponent);
    bool IsAlive();
private:
    const std::string name;
    int healthPoints;
    int manaPoints;
};

Wizard::Wizard(const std::string& name)
    : name(name)
{
    healthPoints = 76 + ThrowDie(25);
    manaPoints = 76 + ThrowDie(25);
}

#include <iostream>
void Wizard::cast(Spell spell, Wizard& opponent)
{
    auto reqEff = spell.Cast();
    if (reqEff.first > manaPoints)
    {
        std::cout << name << " does not have enough mana points to cast " << spell.name << "\n";
    }
    else
    {
        manaPoints -= reqEff.first;
        opponent.healthPoints -= reqEff.second;
        std::cout << name << " casts " << spell.name << ", which does "
            << reqEff.second << " damage to " << opponent.name <<"\n";
    }
}

bool Wizard::IsAlive()
{
    if (healthPoints > 0)
    {
        //std::cout << name << " is still alive!\n"; \\ a lot of text...
        return true;
    }
    std::cout << name << " is dead!" << std::endl;
    return false;
}

#include <iostream>
int main()
{
    std::string name;
    std::cout << "Name the first wizard: ";
    std::cin >> name;
    Wizard wiz1(name);
    std::cout << "Name the second wizard: ";
    std::cin >> name;
    Wizard wiz2(name);

    // Battle start
    while (wiz1.IsAlive() && wiz2.IsAlive()) {
        wiz1.cast(Fireball(), wiz2);
        wiz2.cast(Fireball(), wiz1);
    }

    std::cin.ignore();
}

輸出示例:

Name the first wizard: HarryPotter
Name the second wizard: Voldemort
HarryPotter casts FireBall, which does 13 damage to Voldemort
Voldemort casts FireBall, which does 11 damage to HarryPotter
HarryPotter casts FireBall, which does 12 damage to Voldemort
Voldemort casts FireBall, which does 12 damage to HarryPotter
HarryPotter casts FireBall, which does 7 damage to Voldemort
Voldemort casts FireBall, which does 16 damage to HarryPotter
HarryPotter casts FireBall, which does 8 damage to Voldemort
Voldemort casts FireBall, which does 10 damage to HarryPotter
HarryPotter casts FireBall, which does 8 damage to Voldemort
Voldemort casts FireBall, which does 14 damage to HarryPotter
HarryPotter casts FireBall, which does 16 damage to Voldemort
Voldemort casts FireBall, which does 16 damage to HarryPotter
HarryPotter casts FireBall, which does 16 damage to Voldemort
Voldemort casts FireBall, which does 11 damage to HarryPotter
HarryPotter casts FireBall, which does 14 damage to Voldemort
Voldemort casts FireBall, which does 10 damage to HarryPotter
HarryPotter is dead!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM