-2

I created a custom class and custom hash functions for an unordered_set. Each time I try to insert into that unordered_set, I get a memory error:

malloc: *** error for object 0x9000000000000000: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
Abort trap: 6

It is imperative that I use an unordered_set.

This is my custom class:

template <class T>
class Seed {

  private:
    Point start;
    int seed_size;
    T** data;
    Seed* seed_match;
    T _value;

  public:
    Seed(int x, int y, int s): seed_size(s), data( new T*[s] ), _value( T() ) {
      start = Point(x, y);
      for ( int i = 0; i < seed_size; i++ )
          data[i] = new T[seed_size];

      for ( int i = 0; i < seed_size; i++ ) {
        for ( int j = 0; j < seed_size; j++ ) data[i][j] = NULL;
      }

      seed_match = NULL;
    }

    ~Seed() {
        for ( int x = 0; x < seed_size; x++ ) {
            delete [] data[x];
        }
      delete [] data;
    }

    void add(int x, int y, T color_val) {
      assert( data[x][y] == NULL );
      data[x][y] = color_val;
      _value += color_val;
    }

    bool match ( const Seed &_match ) {
      if ( seed_match == NULL ) {
        seed_match = &_match;
        return true;
      }
      else return false;
    }

    T get_color(int x, int y) const {
      assert( x >= 0 );
      assert( y >= 0 );
      assert( x < seed_size );
      assert( y < seed_size );

      return data[x][y];
    }

    bool operator==( const Seed<T> &b ) {

      for ( int x = 0; x < seed_size; x++ ) {
        for ( int y = 0; y < seed_size; y++ ) {
          if ( get_color(x, y) != b.get_color(x, y) ) return false;
        }
      }

      return true;

    }

    int seed_value() const { return _value; }

};

These are my custom hash functions:

template <class T>
struct SeedEqualByValue {
public:
    bool operator()(const Seed<T> & seed1, const Seed<T> & seed2) const {

        if (seed1.seed_value() == seed2.seed_value())
            return true;
        else
            return false;
    }
};

template <class T>
struct SeedHashByValue {
public:
    size_t operator()(const Seed<T> & s1) const {
        return std::hash<int>()( s1.seed_value() );
    }
};

In my main, I instantiate 3 instances of the Seed class into 3 variables and also instantiate an unordered_set that takes in Seed, with the hash function as my SeedHashByValue struct and my compare function as SeedEqualByValue struct. After creating the unordered_map, anytime I insert a Seed object into the unordered_map, I get an malloc error and I am not sure how to fix this.

These are the contents of my main function:

Seed<int> b(0, 0, 5);
Seed<int> a(0, 0, 5);
Seed<int> c(0, 0, 5);
c.add(4, 4, 100);
a.add(1, 2, 4);
a.add(1, 1, 3);
b.add(1, 1, 3);
unordered_set<Seed<int>, SeedHashByValue<int>, SeedEqualByValue<int> > seeds;
seeds.insert(c); 

Also, Point is just a class that holds x and y values with public member variables int x and int y, in case anyone needed clarification.

TheGodProject
  • 147
  • 2
  • 12
  • 4
    The most likely explanation is that your class [violates the Rule Of Three](https://stackoverflow.com/questions/4172722/what-is-the-rule-of-three) but, unfortunately, without a [mcve] no authoritative answer will be possible. You must edit your question, and make it comply with all requirements of a [mcve], as explained in stackoverflow.com's [help] article, which you should've read before posting your question. – Sam Varshavchik Dec 08 '17 at 00:56
  • 1
    Your class doesn't have a copy-constructor, nor does it have copy-assignment operator overloaded, lack of which, might cause multiple deallocations of the same memory, which is undefined behavior. – Algirdas Preidžius Dec 08 '17 at 01:00

1 Answers1

0

To follow-up on what @Algirdas said, I believe what's happening is that the Seed is shallow-copied into the set, so you end up with a double delete on the same parent pointer, once when the set goes out of scope, and once when the variable goes out of scope.

You'll need to modify how you are handling the data by either transferring it in the assignment operator or by using something like a std::unique_ptr and making sure that it is assigned (which by default transfers ownership).

Jack Zhou
  • 167
  • 1
  • 2