Dark Bit Factory & Gravity

PROGRAMMING => C / C++ /C# => Topic started by: Pixel_Outlaw on July 30, 2008

Title: [C++] n00b questions regarding garbage collection.
Post by: Pixel_Outlaw on July 30, 2008

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.
Title: Re: [C++] n00b questions regarding garbage collection.
Post by: benny! on July 30, 2008
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 ...
Title: Re: [C++] n00b questions regarding garbage collection.
Post by: ninogenio on July 30, 2008
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!
Title: Re: [C++] n00b questions regarding garbage collection.
Post by: Pixel_Outlaw on July 30, 2008
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:
Title: Re: [C++] n00b questions regarding garbage collection.
Post by: ninogenio on July 31, 2008
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.
Title: Re: [C++] n00b questions regarding garbage collection.
Post by: Naptha on July 31, 2008
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.
Title: Re: [C++] n00b questions regarding garbage collection.
Post by: hellfire on July 31, 2008
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 (http://en.wikipedia.org/wiki/Reference_counting) 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 (http://www.boost.org/doc/libs/1_35_0/libs/smart_ptr/smart_ptr.htm) for such mechanisms.

The best way to go, though, still is handling your heap correctly in first place :)
Title: Re: [C++] n00b questions regarding garbage collection.
Post by: Pixel_Outlaw on August 01, 2008
Awesome example of classes containing instances from other classes. I would have easily overlooked handling them properly.
Title: Re: [C++] n00b questions regarding garbage collection.
Post by: Pixel_Outlaw 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?
Title: Re: [C++] n00b questions regarding garbage collection.
Post by: hellfire 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.
Title: Re: [C++] n00b questions regarding garbage collection.
Post by: Jim 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.
Title: Re: [C++] n00b questions regarding garbage collection.
Post by: Pixel_Outlaw on August 14, 2008
Ok got it. Thanks, my book is a bit broad and leaves some holes.