0

I am building a class to manage memory for a program and I am testing it out to make sure it does what I need it to do for my program. Everything works but printing out my mem_end() iterator.

I get this error message: can't dereference out of range vector iterator

Why is this happening? I have confirmed that all elements are in the vector from my temp vector in my testing unit.

Here is my code:

#include <iostream> // input output services
#include <string>   // provides acess to string types
#include <cstdlib>  // provides access to random number generation and dynamic 
            // memory management
#include <ctime>    // provides the ability to manipulate date and time management
#include <vector>   // Part of STL & provides access to vectors that are similar to 
            // dynamic arrays that have the ability to resize themselves
#include <memory>   // more functionality to manage dynamic memory 
#include <cmath>    // access to math funtctions as computations
#include <iomanip>  // Access to set precision
using namespace std;
using std::cout;

// Memory class to manage memory for the program which as a template accepts
// any data type. Manual memory deletion is required
template <class K> // I know its usually T 
class Memory
{
//"Protected" keyword used to limit access outside of Memory but can be accessed by 
// derived classes.
protected:
    // Main array for my Memory class
    vector<K> mem_array;
public:
    Memory() {}; // Default empty constructor for Memory class
    Memory(const Memory&); // Copy constructor
    Memory<K>& operator = (const Memory&); // Assignment operator
    unsigned mem_size();
    void push_back(K);
    void del_mem(int);
    void clear_mem();
    K& operator[](int);
    typedef typename std::vector<K>::iterator iterator; // Iterator functionality 
                                                              // for Memory class
    iterator mem_begin() { return this->mem_array.begin(); }; // returns the first element
                                                              // of mem_array
    iterator mem_end() { return this->mem_array.end(); }; // returns the last element of
                                                          // mem_array
    void show_mem(); 
    void memory_test_unit();
};


int main()
{
    Memory<int> mTest;
    mTest.memory_test_unit(); // For testing code along the way

}

// Method for testing the functionality of my Memory class
template <class K>
void Memory<K>::memory_test_unit()
{
    vector<int> temp = { 5,4,3 };
    setprecision(1);
    Memory<int> mI; //access to Memory with int as the specified data type 
    Memory<double> mD; // same thing with double
    mI.del_mem(1); // Error no elements in mem_array
    cout << mI.mem_size() << endl; // size is zero
    cout << mD.mem_size() << endl; 
    mI.push_back(2);
    mD.push_back(13.4);
    cout << mI.mem_size() << endl; // size is one
    cout << mD.mem_size() << endl;
    //Int array
    mI.show_mem();
    // Double array
    mD.show_mem();
    mI.del_mem(4); // Error mem_array does not have 4 elements
    mI.del_mem(0);
    cout << mI.mem_size() << endl; // size is zero again
    mI.show_mem(); // no elements to print
    for (int i = 0; i < temp.size(); i++) {
        mI.push_back(temp.at(i));
    }
    mI.show_mem(); // Print mem_array
    mI.clear_mem();
    mI.show_mem(); // No elements to print again
    cout << mI.mem_size() << endl; // size is zero again
    for (int i = 0; i < temp.size(); i++) {
        mI.push_back(temp.at(i));
    }
    mI.show_mem(); // Print mem_array
    mI.clear_mem();
    mI.show_mem(); // Print no elements to show
    for (int i = 0; i < temp.size(); i++) {
        mI.push_back(temp.at(i));
    }
    mI.show_mem(); // Prints new loaded vector
    cout << endl;
    cout << *mI.mem_begin(); // should print 5, * to acess iterator
    cout << *mI.mem_end(); // should print 3 - error message here

}

// Memory class things ~
// Copy constructor for my Memory class (allows for deep copy from dissimilar references)
template <class K>
Memory<K>::Memory(const Memory& m) 
{
    this->mem_array = m.mem_array;
}
//Overloaded assignment operator that works with deep copying
template<class K>
Memory<K>& Memory<K>::operator = (const Memory& m)
{
    // Prevents from copying its own memory
    if (this != &m) {
        this->mem_array = m.mem_array;
    }
    return *this;
}
// Method for returning the size of mem_array
template <class K>
unsigned Memory<K>::mem_size()
{
    return this->mem_array.size();
}
// Method to allow acess to mem_array to add data
template <class K>
void Memory<K>::push_back(K dat)
{
    this->mem_array.push_back(dat);
}
// Method to print the contents of mem_array for testing
template <class K>
void Memory<K>::show_mem() 
{
    
    int msize = mem_size();
    for (int i = 0; i < msize; i++) {
        cout << this->mem_array.at(i) << "\n";
    }
    
    if (msize > 0) {
        cout << this->mem_array[0];
    }
    else {
        cout << "\nNo elements to show! \n";
    }
}

// Method to delete a single element from mem_array in a range
template <class K>
void Memory<K>::del_mem(int indx)
{
    if (this->mem_array.size() > 0)
    {
        if (indx >= 0 && indx <= static_cast<int>(this->mem_array.size()) - 1)
        {
            this->mem_array.erase(this->mem_array.begin() + indx);
        }
        else
        {
            std::cout << "\nError(erase): index (" << indx << ") out of bounds of array!\n" << std::endl;
            //exit(0);
        }
    }
    else
    {
        std::cout << "\nError(erase): you can't delete items from an empty array!\n" << std::endl;
        //exit(0);
    }
}
// Method to clear all elements from mem_array
template <class K>
void Memory<K>::clear_mem()
{
    this->mem_array.clear();
}
// Method to overload the subscript operator 
template <class K>
K& Memory<K>::operator[](int indx)
{
    if (indx >= 0 && indx <= static_cast<int>(this->mem_array.size()) - 1)
        return this->mem_array[indx];
    else
    {
        std::cout << "Error(access): index (" << indx << ") out of bounds of array!" << std::endl;
        //exit(0);
    }
}

I used my show_mem() function to verify that all from temp are loaded into mem_array.

Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
  • Side note: "Here's my code." is all-too-often a quick way to say, "I've made no attempt at isolating the bug, so it's no wonder I haven't found it." Consider manufacturing a [mre]. – user4581301 Dec 01 '22 at 19:15
  • `end` is actually "past the end". You could take a look at [this doc](https://en.cppreference.com/w/cpp/container/vector/end) for details. – tromgy Dec 01 '22 at 19:16
  • The `.end()` member of the STL containers gives an iterator to **one past the end**. You can't dereference it. There's likely a duplicate for this but something like this *might* work: `iterator mem_end() { return --(this->mem_array.end()); };`. Related: https://stackoverflow.com/q/5322104/10871073 – Adrian Mole Dec 01 '22 at 19:18

0 Answers0