0

I have recently had some errors (bad_alloc) due to my lack of a destructor.

I currently have two classes, set up in this way:

class ObjOne {
friend class ObjTwo;
public:                  //constructors and some other random methods
    ObjOne(int n) {
    }

    ObjOne() {
    }

private:
    int currSize;
    int size;
    int *jon;
};


 class ObjTwo {
 public:                       //constructors and some other methods
     ObjTwo(ObjOne, int n) {}  //
     ObjTwo() {}
     ObjTwo(const ObjTwo &source) {    //copy constructor
        num = source.num;
        x = source.x;
        myObjOne=source.myObjOne;
     }
     ~ObjTwo() {                          //destructor
           delete #
           delete &x;
           delete &myObjOne;
      }


private:
    ObjOne myObjOne;
    int num, x;
};

and here is my operator= for ObjTwo

ObjTwo& ObjTwo::operator=(const ObjTwo& other) {
    num = source.num;
    x = source.x;
    myObjOne=source.myObjOne;
    return *this;
}

Firstly, my assumptions were (Please correct these if it is incorrect):

ObjOne does NOT need a destructor, as it is only primitive types, and when the compiler will use the default destructor to clean it up. ObjTwo DOES need a destructor, as it contains ObjOne ObjTwo Destructor will need to deallocate memory from x,num and myObjOne.

I have made a few attempts at destructors with this, however I still run into bad_alloc errors (when testing with huge loops etc.) or other errors (with the current one it just crashes when destructor is called).

Any guidance on what I am doing wrong is appreciated

EDIT: I have a bad_alloc exception being thrown when I simply put this in a loop:

ObjTwo b(//some parameters);
ObjTwo a(//some parameters);
for (int i=0; i<20000000; i+) {
    bool x = (a == b);
}

and this is overloaded == operator

bool ObjTwo::operator==(const ObjTwo& other) {

ObjTwo temp = other;

for(int i=myObjOne.x; i>=0; i--) {
    if(myObjOne.get(i)!=temp.myObjOne.get(i)) {
        return false;
    }
}
return true;
}

After some reading on the error it seemed that it was caused to due running out of memory; which my unfunctioning destructor would cause. What could be the problem here?

and the get method simply returns jon[i];

Dax Durax
  • 1,607
  • 5
  • 23
  • 31
  • You didn't `new` anything, there's no need to `delete`. – Simon G. Mar 29 '13 at 20:47
  • 1
    Neither of your examples are correct. You seem to have some misunderstanding. You need a destructor if your class allocates some memory. ObjTwo does not do this and doesn't need a destructor. ObjOne also doesn't on the code you've shown us. But the big red flag in ObjOne is the pointer. If ObjOne allocates some memory and uses `jon` to point to this memory then it surely does need a destructor. That what you should look for, if you classes contain pointers then they may well need a destructor. – john Mar 29 '13 at 20:57
  • After your edit - The error might well be because you are running out of memory. But you've yet to show us any code that allocates memory. All you've shown us so far is badly written destructors. Post complete code. – john Mar 29 '13 at 23:04

2 Answers2

2

You do not need any of your uses of delete. You should only delete something that you have previously allocated with new.

In ObjTwo, the members myObjOne, num, and x definitely should not be deleted. In fact, you should never take the address of a member and delete it. Members are destroyed automatically when the object they are a member of is destroyed.

Consider, for example, having a member which was defined like this:

int* p;

This p is a pointer to int. The pointer itself will be destroyed when the object it is part of is destroyed. However, imagine that in the constructor you dynamically allocate an int object like so:

p = new int();

Now, because new dynamically allocate objects, you will need to delete the object pointed to by p. You should do this in the destructor with delete p;. Note that this isn't destroying p, it's destroying the object it points out. Since p is a member, you should not destroy it manually.

Joseph Mansfield
  • 108,238
  • 20
  • 242
  • 324
  • This is what I thought; however why would I run into bad_alloc errors when I do repeated operations over and over again with no 'new' or 'malloc'. – Dax Durax Mar 29 '13 at 20:49
  • @DaxDurax It could be coming from a number of places. You're best to try and locate the source of the `bad_alloc` exception. – Joseph Mansfield Mar 29 '13 at 20:53
  • @DaxDurax For example, inserting elements into a standard container could result in a `bad_alloc`. – Joseph Mansfield Mar 29 '13 at 20:54
  • @DaxDurax I will echo *everything* that sftrabbit said but add that you seem to have some fundamental misunderstandings about the language. That's not necessarily bad - everyone was a beginner sometime, and to your credit you are trying to learn. But it's important to dispell those misconceptions and understand the underlying concepts properly (such as when destructors are needed and what should and should not be deleted). I would *strongly* recommend picking up [this](http://www.amazon.com/Programming-Principles-Practice-Using-C/dp/0321543726) book. – Nik Bougalis Mar 29 '13 at 20:58
  • 1
    @DaxDurax And just to be clear, whether you need a destructor or not has absolutely nothing to do with whether the types are primitive or not. – Joseph Mansfield Mar 29 '13 at 21:01
1

ObjOne MIGHT need a destructor. This is not about primitive types, but about things like dynamically allocated memory (pointers). You have an int* member, which might be allocated dynamically or at least be a pointer to dynamic memory. So you will need to use delete or delete[] on this one.
What you are doing in ~ObjectTwo is fatal! You are trying to delete memory from the stack -> undefined behavior but will mostly crash. All of your objects/variables are stack-allocated, so you must not delete them...

bash.d
  • 13,029
  • 3
  • 29
  • 42
  • No... `objOne` *may* need a destructor, if the `int*` member is allocated using `new`, but that's not the only way to set that member - he could have initialized it with the address of another integer from somewhere else. In his case it's not allocated at all, so he doesn't need a destructor. – Nik Bougalis Mar 29 '13 at 20:53
  • I corrected my post, but usually you will have a pointer to dynamically allocated memory... It's not clear from These few lines of code. – bash.d Mar 29 '13 at 20:55