0

All of the code is working at this point minus my destructor. When I call it I get a "Debug Assertion Failed!"

Line 52

Expression: _BLOCK_TYPE_IS_VALID(p_Head->nBlockUse)

This is for an assignment that is due in an hour. I am trying to figure it out on my own without any luck. It happens during runtime, and after my process has run to completion and is waiting on a system("PAUSE");

#pragma once
#include "stdafx.h"
#include <array>
#include <stdexcept>
#include <iostream>
#include <string>
// class OutOfBoundsException
// Thrown when an input is outside the availabe range of an array.
// Tells the user what the error was, and the offending parameter
class OutOfBoundsException
{
private:
    int m_input;
    std::string m_error;
public:
    OutOfBoundsException(int input)
    {
        m_input = input;
        m_error = "Out of bounds: ";
    }
    int getInput() const
    {
        return m_input;
    }
    std::string getError() const
    {
        return m_error;
    }
};
class MyVector
{
private:
    // create constant of default capacity set to two and a const BLANK for a blank     array
    const int DEFAULT_CAPACITY = 2;
    const int BLANK = 0;
    // create variables to store the current capacity and the current size
    int currentCapacity;
    int currentSize;
    // create a global pointer for the array
    int* myArrayPtr;
public:
    // MyVector()
    // Default Constructor
    // Sets values per default
    MyVector()
    {
        // sets currentCapacity to default capacity
        currentCapacity = DEFAULT_CAPACITY;
        // sets currentSize to blank
        currentSize = BLANK;
        // creates a dynamic array using default parameters above
        myArrayPtr = new int[currentCapacity];
    }

    // MyVector(int n)
    // Constructor that takes an input for the capacity of the array
    MyVector(int n)
    {
        // sets currentCapacity to n
        currentCapacity = n;
        // sets currentSize to blank
        currentSize = BLANK;
        // creates a dynamic array using parameters above
        myArrayPtr = new int[currentCapacity];

    }
    // ~MyVector()
    // Destructor that cleans up memory allocations within class
    ~MyVector()
    {
        // deletes dynamic array
        delete[] myArrayPtr; // the heap is happy
    }
    // size function
    // Purpose: returns the current size of the array
    // Parameters: N/A
    // Returns: currentSize
    int size() const
    {
        // returns the size of the array << currentSize
        return currentSize;
    }
    // capacity function
    // Purpose: returns the current capacity of the array
    // Parameters: N/A
    // Returns: currentCapacity
    int capacity() const
    {
        // returns the current capacity of the array << currentCapacity
        return currentCapacity;
    }
    // clear function
    // Purpose: deconstructs the array, then reconstructs a default array
    // Parameters: N/A
    // Returns: N/A
    void clear()
    {
        // sets all elements back to defaults
        delete[] myArrayPtr;
        currentCapacity = DEFAULT_CAPACITY;
        currentSize = BLANK;
        myArrayPtr = new int[currentCapacity];
    }
    // push_back function
    // Purpose: pushes n into the back of the array, if the array is too small to hold another value, it doubles the size of the array.
    // Parameters: int n
    // Returns: N/A
    void push_back(int n)
    {
        if (currentSize == currentCapacity)
        {
            if (currentCapacity == BLANK)
            {
                clear();
            }
            else
            {
                // create a local array that will be destroyed as soon as
                int* temp = new int[currentCapacity * DEFAULT_CAPACITY];
                for (int i = 0; i < currentCapacity; i++)
                {
                    temp[i] = myArrayPtr[i];
                }
                delete[] myArrayPtr;
                currentCapacity *= DEFAULT_CAPACITY;
                myArrayPtr = temp;
            }
        }
        if (currentSize != BLANK)
        {
            myArrayPtr[currentSize] = n;

        }
        else
        {
            myArrayPtr[currentSize] = n;
        }
        currentSize++;

    }
    // at function
    // Purpose: returns value at n
    // Parameters: int n
    // Returns: myArrayPtr[n]
    // Throws OutOfBoundsException if n is greater than the index of the last item in the array
    int at(int n) const
    {
        try
        {
            // returns the value at n
            if (n > currentSize - 1)
                throw OutOfBoundsException(n);
            else
                return myArrayPtr[n];
        }
        catch (OutOfBoundsException e)
        {
            std::cout << std::endl << e.getError() << e.getInput() << std::endl;
        }
        return myArrayPtr[n];
    }
};

The code causing this error is a simple runner class just created for the sole purpose of testing it.

#pragma once
#include "stdafx.h"
#include "MyVector.h"
#include <iostream>
using namespace std;
int main()
{
MyVector hello(10);
// hello.~MyVector();


hello.push_back(-1);
hello.push_back(-1);
hello.push_back(-1);
hello.push_back(-1);
hello.push_back(0);

hello.~MyVector();
system("PAUSE");
return 0;
}
  • 1
    http://en.wikipedia.org/wiki/Rule_of_three_(C%2B%2B_programming) – Chad Feb 20 '14 at 05:53
  • Please post the code that called uses this code, possibly you are deleting the pointer twice. – 51k Feb 20 '14 at 05:57
  • 2
    Without knowing *everywhere* this is used in your program, speculation is all you get. That said, your vector class is not Rule-of-Three compliant. If it is ever, **ever**, copied (assignment, copy-construction including passed as a by-value parameter to some function, etc.) you will be setting up two vectors that reference the same internal buffer, one will delete it with success, the other will be holding a dangling pointer that can the error you see (if you're *lucky*). – WhozCraig Feb 20 '14 at 06:03
  • as indicated by @WhozCraig try writing a copy constructor, which will allocate a new memory for a new copy.. :) – 51k Feb 20 '14 at 06:04
  • 1
    ... and a *correct* assignment operator. – WhozCraig Feb 20 '14 at 06:06
  • 1
    Chad's right... if your client code copies a `MyVector` you're in deep trouble - you need to do a "deep copy" in a custom `operator=(const MyVector&)` and copy constructor `MyVector(const MyVector&)`. Separately, your `at()` function is all wrong... it should just do what's inside your `try` block, and leave the catching to the client code. It should return `int&` too, so the caller can assign to that element. – Tony Delroy Feb 20 '14 at 06:11

2 Answers2

0

The destructor is called twice. hello.~MyVector() is the first. :-)

user3277268
  • 165
  • 3
0

Your MyVector object is not allocated by yourself, so the program will take care of deleting it automatically. If you want to delete it, simply allocate it yourself this way:

MyVector    *mv = new Myvector(...);

[...]
delete mv;
return ;

delete will automatically call the object destructor.

By the way, http://www.cplusplus.com/articles/y8hv0pDG/

Coplien is the way, even when you don't need them, take the habitude to always define them.