我正在学习 C++ 课程,但我对编程并不是完全陌生,因为我了解很多 Java 和一些 Python。这是我以前从未见过的:我有一个程序,该程序应该清点方舟上的动物,并将它们按 1 个月老化,并模拟方舟上的人口增长。我通过调试器发现它工作正常,直到第二个鱼对象通过ageOneMonth方法,然后我得到一个异常
“noahsArkApp.exe 中的 0x00007FF779B38CBB 抛出异常:0xC0000005:读取位置 0xFFFFFFFFFFFFFFFF 时发生访问冲突。”
程序退出(进程20984),退出代码为-1073741819。
更奇怪的是,每次发生这种情况时,我的诺顿防病毒软件都会显示弹出窗口“潜在威胁已阻止”,详细信息中描述的操作是“可疑进程试图修改受 Data Protector 保护的文件的安全性”。这里可能发生了什么?我该如何修复这个异常?我需要禁用诺顿吗?
#include <iostream>
#include <string>
#include <vector>
#include <memory> // for smart pointers? Googled for a fix to memory issue but still having problems :(
#include <cstdlib> // for srand() and rand() functions
#include <ctime> // for time() function
using namespace std;
// enum classes to limit options for type and gender
enum class Type { MAMMAL, BIRD, FISH };
enum class Gender { FEMALE, MALE };
class Animal {
protected:
Type type;
string species;
Gender gender;
int ageInMonths;
public:
Type getType() { return type; }
string getName() { return species; }
Gender getGender() { return gender; }
int getAgeInMonths() { return ageInMonths; }
Animal(Type _type, string _name, Gender _gender, int _ageInMonths) : type(_type), species(_name), gender(_gender), ageInMonths(_ageInMonths) {};
virtual void ageOneMonth() {
ageInMonths++;
}
virtual void giveBirth(vector<unique_ptr<Animal>>& animals) {
// Default implementation does nothing
}
virtual void identifyAnimal() const {
string genderStr = (gender == Gender::MALE) ? "male" : "female";
cout << "I am a " << genderStr << " " << species << ", " << ageInMonths << " months old." << endl;
}
};
class Mammal : public Animal {
public:
Mammal(Type _type, string _name, Gender _gender, int _ageInMonths) : Animal(Type::MAMMAL, _name, _gender, _ageInMonths) {}
virtual void giveBirth(vector<unique_ptr<Animal>>& animals) override {
if (gender == Gender::FEMALE && ageInMonths % 12 == 0) {
Gender newbornGender = (rand() % 2 == 0) ? Gender::MALE : Gender::FEMALE;
animals.push_back(make_unique<Mammal>(getType(), getName(), newbornGender, 0));
}
}
};
class Bird : public Animal {
public:
Bird(Type _type, string _name, Gender _gender, int _ageInMonths) : Animal(Type::BIRD, _name, _gender, _ageInMonths) {}
virtual void giveBirth(vector<unique_ptr<Animal>>& animals) override {
if (gender == Gender::FEMALE && ageInMonths % 9 == 0) {
Gender newbornGender = (rand() % 2 == 0) ? Gender::MALE : Gender::FEMALE;
animals.push_back(make_unique<Bird>(getType(), getName(), newbornGender, 0));
}
}
};
class Fish : public Animal {
public:
Fish(Type _type, string _name, Gender _gender, int _ageInMonths) : Animal(Type::FISH, _name, _gender, _ageInMonths) {}
virtual void giveBirth(vector<unique_ptr<Animal>>& animals) override {
if (gender == Gender::FEMALE && ageInMonths % 6 == 0) {
Gender newbornGender = (rand() % 2 == 0) ? Gender::MALE : Gender::FEMALE;
animals.push_back(make_unique<Fish>(getType(), getName(), newbornGender, 0));
}
}
};
int main() {
srand((unsigned int)time(0));
vector<unique_ptr<Animal>> animals;
// Add initial animals to the ark
animals.push_back(make_unique<Mammal>(Type::MAMMAL, "Cat", Gender::FEMALE, 11));
animals.push_back(make_unique<Mammal>(Type::MAMMAL, "Cat", Gender::MALE, 10));
animals.push_back(make_unique<Mammal>(Type::MAMMAL, "Dog", Gender::FEMALE, 12));
animals.push_back(make_unique<Mammal>(Type::MAMMAL, "Cat", Gender::MALE, 9));
animals.push_back(make_unique<Fish>(Type::FISH, "Goldfish", Gender::FEMALE, 5));
animals.push_back(make_unique<Fish>(Type::FISH, "Goldfish", Gender::MALE, 5));
animals.push_back(make_unique<Fish>(Type::FISH, "Shark", Gender::FEMALE, 6));
animals.push_back(make_unique<Fish>(Type::FISH, "Shark", Gender::MALE, 6));
animals.push_back(make_unique<Bird>(Type::BIRD, "Eagle", Gender::FEMALE, 8));
animals.push_back(make_unique<Bird>(Type::BIRD, "Eagle", Gender::MALE, 11));
animals.push_back(make_unique<Bird>(Type::BIRD, "Parakeet", Gender::FEMALE, 17));
animals.push_back(make_unique<Bird>(Type::BIRD, "Parakeet", Gender::MALE, 13));
int months = 0;
while (true) {
cout << "\nYou have been on the ark for " << months << " months. What would you like to do?" << endl;
cout << "1 - Let another month pass" << endl;
cout << "2 - Check inventory" << endl;
cout << "3 - Quit" << endl;
int choice;
cin >> choice;
if (choice == 1) {
months++;
// Age all animals by one month and let them give birth
for (auto& animal : animals) {
animal->ageOneMonth();
animal->giveBirth(animals);
}
}
else if (choice == 2) {
// Display inventory
cout << "\nInventory:" << endl;
int count = 1;
for (const auto& animal : animals) {
cout << "Animal #" << count++ << ": ";
animal->identifyAnimal();
}
}
else if (choice == 3) {
// Clean up memory
animals.clear();
break;
}
}
return 0;
}
我不知道诺顿在做什么,但就你的程序崩溃的原因而言,我相信这是因为你的
giveBirth()
函数正在修改 animals
向量,而 main()
中的 for 循环正在迭代在向量上,这是一个禁忌,因为它会使迭代器对象无效。
为了测试我的理论,我用以下代码替换了
choice==1
代码:
months++;
// Age all animals by one month and let them give birth
vector<unique_ptr<Animal>> temp;
for (auto& animal : animals) {
animal->ageOneMonth();
animal->giveBirth(temp);
}
// Now that we are done iterating over animals
// we can go ahead and add the new infants to the vector
for (auto& animal : temp) {
animals.push_back(std::move(animal));
}
....有了这个改变,我就不能再让程序崩溃了。