Crystal
Crystal

Reputation: 15

What in my C++ program could be setting off my Norton antivirus? Also struggling to debug and fix an exception, maybe memory related?

I'm taking a C++ class but I'm not completely new to programming as I know a good deal of Java and some Python. This is something I have never seen before: I have a program that supposed to inventory animals on an ark and age them by 1 month and simulate the population growth on the ark. I went through with the debugger and found it works fine until the second fish object goes through the ageOneMonth method, then I get an exception

"Exception thrown at 0x00007FF779B38CBB in noahsArkApp.exe: 0xC0000005: Access violation reading location 0xFFFFFFFFFFFFFFFF."

The program exits with (process 20984) exited with code -1073741819.

What's even more weird is each time this happens my Norton antivirus shows a popup "Potential Threat Blocked" The action described in the details is "suspicious process attempted to modify security of a file protected by Data Protector". What could be going on here? How do I fix this exception? Do I need to disable Norton?

#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;
}

Upvotes: 1

Views: 224

Answers (1)

Jeremy Friesner
Jeremy Friesner

Reputation: 73219

I don't know what Norton is on about, but as far as why your program is crashing, I believe it is because your giveBirth() function is modifying the animals vector while the for-loop in main() is iterating over that same vector, and that is a no-no because it invalidates the iterator object.

To test my theory, I replaced the choice==1 code with the following:

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));
}

.... and with that change I can no longer get the program to crash.

Upvotes: 2

Related Questions