Search code examples
c++oopinheritancedestructorvirtual-destructor

Destroying vectors of dynamic arrays via destructor in c++


I'm working on one of assignments to do with image manipulation (blending and zooming) and I've ran into a problem that I have hard time overcoming.

Structure of my application

Class Image

  • rgb struct: contains floats (they're flattened pixels) and overloaded operators.
  • pixels: a 1d array of pixels which is initialized via constructor to be h * w
  • Class destructor.

Destructor looks a little like this...

virtual ~Image()
{
    if (pixels != NULL)
        delete[] pixels;
}

Now I'm using another class called Filter which inherits from Image

class Filter: public class Image

  • std::vector of Image imgStack; Container for images that I'm going to blend
  • std::vector of Rgb pixelBuffer; A container for the pixels for each images one pixel. This is not dynamic so I'm not worried about deleting this.

Destructor for the derived class.

~Blend()
{
    delete &imageStack;
}

what this part of my main.cpp looks like...

while (userInput != 5)
{
    switch(userInput)
    case 1:
    {
        Blend *meanImage = new Blend(3263, 2505, 13);
        meanImage->writePPM("Mean_" + std::to_string(count) + ".ppm");//every iteration, the file name is unique
        meanImage->~Blend();
    }
}

In my main.cpp I'm basically running 13 images into the Blend object which stores the images in the vector container to do all my functionality on. During the run time the space used is around 1.3GB, but since my object is in a loop (i have a menu for multiple functionality) the object doesn't usually leave the scope so the destructor isn't automatically called, so I call it manually like this; medianImage->~Blend(); Now the all the error says is that my application "has triggered a breakpoint" and that's it... Note, no breakpoint is found anywhere. I'm aware that it's generally bad to use dynamic arrays because it causes all sorts of memory problems (if it's done by me), but I want to fix this just so I know how to solve these in the future.

If you have any questions of the code, I can post snippers.

Edit: here's an my Blend class.

#pragma once
#include "stdafx.h"
#include "Image.h"
#include <vector>
#include <string>
class Blend : public Image
{
private:
    std::vector<Image> imageStack;
    std::vector<Rgb*> pixelBuffer;//only works with pointers (no copying)
    int m_noOfImages;

    Rgb* getMedianFromSet();
    Rgb getMeanFromSet();
    Rgb getStdDev(Rgb meanPix);
public:
    Blend(int width = 0, int height = 0, int noOfImages = 0):Image(width, height), m_noOfImages(noOfImages), imageStack(noOfImages), pixelBuffer(noOfImages)
    {}
public:
    void stack(bool push = true);
    void meanBlend();
    void medianBlend();
    void sigmaClipping(float sigma = 0.5f);

    ~Blend()
    {
        delete &imageStack;
    }
};

Solution

  • #pragma once
    #include "stdafx.h"
    #include "Image.h"
    #include <vector>
    #include <string>
    #include <memory>
    class Blend : public Image
    {
    private:
        std::vector<Image> imageStack;
        // Changed to shared_ptr<T>  could use unique_ptr<T> depending on need.
        std::vector<std::shared_ptr<Rgb>> pixelBuffer;//only works with pointers (no copying)
        int m_noOfImages;
    
        Rgb* getMedianFromSet();
        Rgb getMeanFromSet();
        Rgb getStdDev(Rgb meanPix);
    public:
        Blend(int width = 0, int height = 0, int noOfImages = 0):Image(width, height), m_noOfImages(noOfImages), imageStack(noOfImages), pixelBuffer(noOfImages)
        {}
    public:
        void stack(bool push = true);
        void meanBlend();
        void medianBlend();
        void sigmaClipping(float sigma = 0.5f);
    
        // Clear Entire Buffer
        void cleanup() {
            // When using the heap with smart pointers
            for ( auto item : containerVariable ) {
                item.reset();
                item = nullptr;
            }
            containerVariable.clear();
        }
    
        // Remove Single Element
        void remove( unsigned idx ) {
            // Write function to remove a single element from vector
        }
    
        ~Blend()
        {
            // This is definitely wrong here: You are trying to delete a reference 
            // to a template container that is storing `Image` objects that
            // are on the stack. 
            // delete &imageStack;
        }
    };
    

    It is better to write a function to clean up memory, and to remove specific elements from containers when using dynamic memory than it is to use a class's destructor.