'Deleting a pointer from a vector... Error: terminate called after throwing an instance of 'std::bad_alloc' what(): std::bad_alloc

I'm getting the error after I delete a pointer from the vector and try to delete a second one. I'm still new to pointers

I created a base class of shapes and have multiple shapes derived classes not shown here and I have to store them in a vector of pointers.

I ask the user to add shapes of their choice measures and calculate the volumes then I also ask what shapes they want to remove.

#include <string>
#include <iostream>
#include <vector>
#include <iomanip>
#define _USE_MATH_DEFINES
#include <cmath>

using namespace std;

class Luggage {
    private:
        static double totalVolume;
    
    protected:
        string type;
        static int count;
        static int serialGen;
        int serialNum;
    
    public:
        Luggage() {
            type = "Luggage";
            count++;
            serialNum = serialGen++;
            cout<<"Generating Luggage"<<getSN()<<endl;
        }
        
        // 'static' can only be specified in the class header file not source
        void static updateVolume(double inVolume) {
            totalVolume += inVolume;
        }
        
        virtual 
        ~Luggage() {
            cout<<"Luggage Destructor"<<getSN()<<endl;
            count--;
        }
        
        static int getCount() {
            return count;
        }
        
        string getType() {
            return type;
        }
        
        string getSN() {
            return "(SN: " + to_string(serialNum) + ")";
        }
        
        virtual double getVolume()=0;
        
        static double getLuggageVolume() {
            return totalVolume;
        };
        
        friend ostream & operator<<(ostream & out, Luggage * lptr) {
            out<<setw(10)<<left<<lptr->getType()<<": "
                <<setw(6)<<right<<setprecision(1)
                <<fixed<<lptr->getVolume()<<"  ~  "<<lptr->getSN();
            return out;
        }
};



class Box : public Luggage {
    private:
        double length, width, height;
        static int count;
        static double totalVolume;
        
    public:
        Box(double l, double w, double h){
            count++;
            type = "Box";
            length = l;
            width = w;
            height = h;
            cout<<"Generating a Box with a Volume: "<<getVolume()<<getSN()<<endl;
            updateVolume(getVolume());
        }
        
        ~Box() {
            count--;
            updateVolume(getVolume() * -1);
            cout<<"Destroying a Box with Volume: "<<getVolume()<<getSN()<<endl;
        }
        
        double getVolume() {
            return length*width*height;
        }
        
        static int getCount() {
            return count;
        }
        static double getTotalVolume() {
            return totalVolume;
        }
};


int main() {
    // Your main program will create a container of luggage and be able to add luggage items
    // and remove them as well. This container will be a vector of luggage pointers.
    vector<Luggage*> container;

    int input;  // Main Menu User input
    bool io = true;
    while(io){
        // Main Menu
        cout << "\n----Main Menu----\n"
                "1) Add Luggage to storage container\n"
                "2) Remove Luggage from storage container\n"
                "3) Show all luggage\n"
                "4) Show total volumes\n"
                "5) Exit\n\n"
                "Enter: ";
        Luggage *lptr;

        cin >> input;
        if(input == 1){
            int shapeChoice;
            cout<<"\nWhat Shape do you want? "<<endl
                    <<"1) Box"<<endl
                    <<"2) Cube"<<endl
                    <<"3) Cylinder"<<endl
                    <<"4) Pyramid"<<endl
                    <<"5) Sphere"<<endl;
            cin>>shapeChoice;

            switch (shapeChoice){
                case 1: {   // Box
                    double length, width, height;
                    cout << "\nEnter length of Box: ";
                    cin >> length;
                    cout << "Enter width of Box: ";
                    cin >> width;
                    cout << "Enter height of Box: ";
                    cin >> height;
                    lptr = new Box(length, width, height);
                    container.push_back(lptr);
                    break;
                }
                default:
                    cout << "Bad choice! Please try again later.\n";
                    break;
            }

        }else if(input == 2) {

            int count = 0;
            for(auto l:container) // container is vector<Luggage*>
                cout << ++count << ") "<< l << endl;

            cout<<"What element do you want to remove? "<<endl;
            int removeChoice;
            cin>>removeChoice;
            removeChoice-=1;

            delete (lptr);
            container.erase(container.begin()+removeChoice);

        }
}


Solution 1:[1]

delete (lptr);

This statement is wrong.

lptr is pointing at the last Box object pushed into the vector. If nothing was pushed yet, this statement causes undefined behavior since lptr is uninitialized before the 1st push. Otherwise, you are destroying the last object pushed, and then you are left with a dangling pointer, which will then fail on the next delete, causing undefined behavior again, unlese you push a new object that updates lptr beforehand.

That statement should be this instead:

delete container[removeChoice];

or safer:

delete container.at(removeChoice);

since you are not validating removeChoice beforehand.

But either way, you really shouldn't new/delete objects manually in modern C++. Use smart pointers instead, in this case std::unique_ptr<Luggage>, and let it deal with destroying objects for you.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1