Author Topic: [C++] n00b questions regarding garbage collection.  (Read 7077 times)

0 Members and 1 Guest are viewing this topic.

Offline Pixel_Outlaw

  • Pentium
  • *****
  • Posts: 1389
  • Karma: 84
    • View Profile

OK so I'm now in hour 8 of my C++ programming book. I decided to take up a language that is very common in the workplace. Currently my book tells how to create some nice "Cat" objects but it does not specify how to handle removing instances of the "Cat" class from memory. I'm  mostly familiar with Blitzmax which has automatic garbage collection. This means that once there is no code using or holding an instance that instance is destroyed. For example if I have a linked list holding some "Student" objects, I can remove instances from the list and they will be freed from memory. Now my question becomes how to free instances of a class in C++. What "gotchas" do I need to watch out for when working with a language that does not have garbage collection?

I'm enjoying C++ now and it is becoming more simple that it was in my previous 7 attempts. Learning Blitzmax was a good idea because it forced me to fill in some gaps.
Challenge Trophies Won:

Offline benny!

  • Senior Member
  • DBF Aficionado
  • ********
  • Posts: 4384
  • Karma: 228
  • in this place forever!
    • View Profile
    • bennyschuetz.com - mycroBlog
Hmm ... let's see if my poor C++ knowledge can answer you question.

There are indeed some trapfalls using C++ and not having an automatic
mechanism like a garbage collector. I guess there are some algorithms
and techniques around which replaces a gc in C++ - but I guess all starts
doing it manually.

Garbage collection in general deals with the dynamic memory (heap). So,
if you create a new object with new operator you reserve memory
for it on the heap.

Now there are two possible major mistakes that can happen.

A.) You forget to free the memory with delete - then you waste
memory and you have a memory leak.

B.) You delete/free the object in memory - but forget to set the pointer
to null. In this case (called dangling pointers) - you point into the
memory without having the object at that address anymore.

Guess the other C++ gurus here can tell you this more precisely ...
[ mycroBLOG - POUET :: whatever keeps us longing - for another breath of air - is getting rare ]

Challenge Trophies Won:

Offline ninogenio

  • Pentium
  • *****
  • Posts: 1668
  • Karma: 133
    • View Profile
delete [] Object;

should take care of it, delete calls the destructor from the class as well as freeing the class from memory.

now in your class if you dynamically allocate memory anywhere you should free it in the destructor using delete as well.and you always use delete with new.

one important thing to remember is never call the the destructor yourself ie Object[0]->~Object(); let delete worry about it!
« Last Edit: July 31, 2008 by ninogenio »
Challenge Trophies Won:

Offline Pixel_Outlaw

  • Pentium
  • *****
  • Posts: 1389
  • Karma: 84
    • View Profile
Ok thanks guys. I'm just a bit paranoid about crashing things when making something like a particle system where alot of deleting and creating is going on.

 :goodpost:
Challenge Trophies Won:

Offline ninogenio

  • Pentium
  • *****
  • Posts: 1668
  • Karma: 133
    • View Profile
i always use taskmanager as the code is running to veiw the availible memory on startup/shutdown and as the code is running, if you have any leakage you will see your memory being eaten up.
Challenge Trophies Won:

Offline Naptha

  • C= 64
  • **
  • Posts: 53
  • Karma: 3
    • View Profile
There are a few leaks to watch out for that I've come across:

Code: [Select]
Cat* kitty1 = new Cat();
Cat* kitty2 = new Cat();
kitty1 = kitty2;

The instance of Cat originally pointed to by kitty1 no longer has a pointer and therefore can't be freed.

Code: [Select]
void oops()
{
    Cat* kitty = new Cat();
}

Pointer kitty is local to function oops(), if it goes out of scope (without being returned from the function or otherwise passed on) then the instance of Cat no longer has a pointer and therefore can't be freed.

Code: [Select]
Cat* kitty = new Cat("Molly");
kitty = new Cat("Betty");
delete kitty;

First we create a cat called Molly, then we want kitty to point to a new cat called Betty. Finally we delete kitty.  Betty is history, but we reassigned the only pointer to Molly, so that instance can't be freed.

I'm sure there are lots more but that's all I know (I'm also a noob)  ;D

Oh, and it's worth remembering that you don't HAVE to instantiate classes on the heap.
« Last Edit: July 31, 2008 by Naptha »

Offline hellfire

  • Sponsor
  • Pentium
  • *******
  • Posts: 1294
  • Karma: 466
    • View Profile
    • my stuff
What's a little bit tricky about C++'s memory handling is to find a consistent definition of who's responsible for the creation and deletion of an object.

This might be a bit far out for the beginning, but most of that hassle is eliminated when one just specifies an object's "owner" and delete the object along with its' owner.
This can be achieve by a simple base-class:
Code: [Select]
class BaseObject
{
public:
  // constructor
  BaseObject(BaseObject *parent= NULL)
  : mParent(parent)
  {
    // if a parent is specified, notify the parent about its' new child.
    if (mParent)
      mParent->addChild(this);
  }

  // destructor
  ~BaseObject()
  {
    // remove the child from the parent
    if (mParent)
      mParent->deleteChild(this);

    // delete all children
    while (!mChildList.empty())
      delete mChildList.pop_front();
  }

  void addChild(BaseObject *child)
  {
    // add new child to child-list
    mChildList.insert(child);
  }

  void deleteChild(BaseObject *child)
  {
    // erase child from child-list
    mChildList.erase(child);
  }

private:
  BaseObject *mParent;   // pointer to the parent-object
  Set<BaseObject*> mChildList;  // list of child-objects (most standard-containers do as well)
}

Now all you do is derive from "BaseObject" and use it like this:
Code: [Select]
void MyClass::doWickedThings()
{
  Object *obj1= new Object(this);
  Object *obj2= new Object(this);
  Object *obj3= new Object(this);
  // ...
}
Now when deleting MyClass, all objects allocating along with it get deleted automatically.

Quote
- then the instance no longer has a pointer and therefore can't be freed.
- but we reassigned the only pointer, so that instance can't be freed
A solution for this would be overloading the "=" operator, so that an already existing object gets deleted first or, more generally, handle a reference counter to test if any other instances are still refering to the object (realizing most of a garbage-collector).
You can have a look at boost for such mechanisms.

The best way to go, though, still is handling your heap correctly in first place :)
« Last Edit: July 31, 2008 by hellfire »
Challenge Trophies Won:

Offline Pixel_Outlaw

  • Pentium
  • *****
  • Posts: 1389
  • Karma: 84
    • View Profile
Re: [C++] n00b questions regarding garbage collection.
« Reply #7 on: August 01, 2008 »
Awesome example of classes containing instances from other classes. I would have easily overlooked handling them properly.
Challenge Trophies Won:

Offline Pixel_Outlaw

  • Pentium
  • *****
  • Posts: 1389
  • Karma: 84
    • View Profile
Re: [C++] n00b questions regarding garbage collection.
« Reply #8 on: August 14, 2008 »
Just to make sure that I'm still on the same page,

If I create a new instance of a class in a function,

say

null function()
{
Human Ryan,
}

Do I need to delete the instance "Ryan" or is he deleted when the function returns?
Challenge Trophies Won:

Offline hellfire

  • Sponsor
  • Pentium
  • *******
  • Posts: 1294
  • Karma: 466
    • View Profile
    • my stuff
Re: [C++] n00b questions regarding garbage collection.
« Reply #9 on: August 14, 2008 »
Local variables are stored on the stack and are removed automatically when the function returns (stack decreases).
If you instead allocate the variable on the heap...
Code: [Select]
void function()
{
  Human *Ryan= new Human();
}
...you have to delete it manually.
The stack-concept ensures that local variables stay available for called subroutines (stack increases), but require copying if the callee wants to return them.
Challenge Trophies Won:

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: [C++] n00b questions regarding garbage collection.
« Reply #10 on: August 14, 2008 »
Yup, Ryan will disappear at the end of the function scope.  But if Ryan()'s constructor allocated memory or created any other non-C++ resource which wasn't freed in ~Ryan() then there will likely be a leak.
Challenge Trophies Won:

Offline Pixel_Outlaw

  • Pentium
  • *****
  • Posts: 1389
  • Karma: 84
    • View Profile
Re: [C++] n00b questions regarding garbage collection.
« Reply #11 on: August 14, 2008 »
Ok got it. Thanks, my book is a bit broad and leaves some holes.
Challenge Trophies Won: