Search code examples
c++destructor

Design: How to avoid calling destructor?


I got a Window class that is a wrapper to some C struct.
The class has a static vector<Window*> windows_ that is a list containing created windows.
Window constructor does two things:

  • handle_ = SDL_CreateWindow( ... ); that basically allocates the C struct and store the pointer in a member variable handle_;
  • pushes this in the list.

Window destructor does three things but only if handle_ is not a nullptr:

  • SDL_DestroyWindow() deallocates the C struct;
  • removes this from the list.
  • handle_ = nullptr;

Then, in my main I declare a Window as a local variable.
When the window receives the CLOSE event, I call that window's destructor.
Then, when the window goes out of scope, the window's destructor gets called again and I receive a segmentation error.

I know expicitly calling a destructor is delicate but I don't really know why.
So the question is twofold:

Why is it crashing?

What design can I use to avoid calling the destructor?


Solution

  • You should post some code so we can see exactly what is happening, but you're right that you shouldn't manually call the destructor because that will cause undefined behavior (see AliciaBytes' answer). Instead, add a method to the class to close the window, and use the class to provide a safe interface to the SDL window functions. Here is a sketch:

    class Window {
    private:
        SDL_Window *window_;
    
    public:
        Window() : window_(nullptr) { }
        Window(const Window &) = delete;
        Window(Window &&w) : window_(w.window_) { w.window_ = nullptr; }
        Window(const char* title, int x, int y, int w, int h, Uint32 flags)
            : window(SDL_CreateWindow(title, x, y, w, h, flags))
        { }
    
        ~Window()
        {
            if (window_ != nullptr)
                SDL_DestroyWindow(window_);
        }
    
        Window &operator=(const Window &) = delete;
        Window &operator=(Window &&w)
        {
            if (window_) { SDL_DestroyWindow(window_); window_ = nullptr; }
            window_ = w.window_;
            w.window_ = nullptr;
        }
    
        operator bool() const
        {
            return window_ != nullptr;
        }
    
        void close()
        {
            if (window_ != nullptr) {
                SDL_DestroyWindow(window_);
                window_ = nullptr;
            }
        }
    };