Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Destructor is not being invoked

I have written the following code to implement a stack.

#include<iostream>
using namespace std;

class stack
{
    public:
        int *top;
        int  size, capacity;
    
    stack(int c):capacity(c){
        size = 0;
        top = new int[capacity];
        capacity = capacity - 1;
    }
    
    ~stack() // deleting the stack at the end of program
    {
        delete[] top;
        top = NULL;
        cout << "deleted the stack" << endl;
    }
    
    void push(int data)
    {
        // Is there is a space
        if(is_stackFull())
        {
            cout << "stack is full" << endl;
            return;
        }
        
        // populate the data
        *top   = data;
        
        // updating the stack variables
         top  += 1;
         size += 1;
        return;
    }
    
    void pop()
    {
        // is stack empty
        if(is_stackEmpty())
        {
            cout << "stack is empty" << endl;
            return; 
        }
        
        // update the stack variables
        top  -= 1;
        size -= 1;
        
        return;
    }
    
    bool is_stackFull()
    {
        return (size == capacity);
    }
    
    bool is_stackEmpty()
    {
        return (size == 0);
    }
};


int main()
{
    stack s(10);
    s.push(15);
    //s.pop(); // what happens to the output when i comment out this code?
    
    return 0;
}

In the code, the destructor is not being invoked when I commented the s.pop() method.

Can any one explain the tech reason behind such behavior?

I tried understanding the ways to invoke the destructor in a C++ class.

like image 396
siva ramaraju siv Avatar asked Feb 03 '26 04:02

siva ramaraju siv


2 Answers

In stack::push you are changing what top points to. Thus it can no longer be deleted. If you push once and pop once, top goes back to what it was, and the error does not occur.

Rather than modifying the top pointer, you can keep track of a top index and modify that. E.g.

#include <iostream>
#include <algorithm>
#include <optional>

template <class T>
class Stack {
    public:
    using size_type = std::size_t;

    // Constructor
    Stack(size_type cap)
    : capacity(cap), top(0), data(new T[cap])
    { }

    // Destructor
    ~Stack() {
        delete[] data;
    }

    // Copy constructor
    Stack(const Stack& s)
    : capacity(s.capacity), top(s.top), data(new T[s.capacity])
    {
        std::copy(s.data, s.data+capacity, data);
    }

    // Copy assignment
    Stack& operator=(const Stack& s) {
        top = s.top;
        capacity = s.capacity;
        delete[] data;
        data = new T[capacity];
        std::copy(s.data, s.data+capacity, data);
        return *this;
    }

    // Move constructor
    Stack(Stack&& s)
    : capacity(s.capacity), top(s.top), data(s.data)
    {
        s.capacity = 0;
        s.top = 0;
        s.data = nullptr;
    }

    size_type get_capacity() const { return capacity; }
    size_type get_top() const { return top; }
    bool is_empty() const { return top == 0; }
    bool is_full() const { return top == capacity; }

    bool push(T val) {
        if (is_full()) return false;

        data[top++] = val;
        return true;
    }

    std::optional<T> pop() {
        if (is_empty()) return std::nullopt;

        return std::optional<T>{data[--top]};
    }

    private:
    T *data;
    size_type top;
    size_type capacity;
};

int main() {
    auto s = Stack<int>(10);

    s.push(19);
    s.push(67);

    std::cout << s.pop().value() << " "
              << s.pop().value() << std::endl;
}
like image 122
Chris Avatar answered Feb 05 '26 16:02

Chris


The destructor is being invoked, it's just not doing what you expect. When you call push but not pop, top ends up pointing one space to the right of where it started. So, the destructor ends up calling delete on a different address from the one returned by new, which is undefined behavior. That means your code can basically do whatever it wants, which in this case apparently means not printing your deleted the stack message. When I run it, I get

free(): invalid pointer
Aborted (core dumped)

To fix it, you could add a line top -= size to your destructor before you call delete so that it is pointing to the same place it started.

like image 23
micaiah Avatar answered Feb 05 '26 18:02

micaiah