2

Does anyone know of a good compiler for c++ that supports garbage collection. I know that they were considering it for c++11 but didn't implement it.

20
  • 23
    Who needs garbage collection with RAII in place? Commented May 6, 2013 at 4:49
  • 5
    @aaronman, Don't forget std::unique_ptr. That's the one you should be using by default. Commented May 6, 2013 at 5:00
  • 3
    What you are looking for is called managed C++. Visual Studio/.NET supports that. However, it's not standardized so I would not advice it unless you are certain you will be developing in MS for eternity. Smart pointers can give you pretty everything you need (I'm not sure why you are looking for garbage collected C++, the compiler will most likely not solve the 3rd party memory leaks you are mentioning). Commented May 6, 2013 at 5:19
  • 3
    MIhgt not be what you are looking for but take a look at Boehm's conservative GC, hpl.hp.com/personal/Hans_Boehm/gc. Can be added to existing code fairly easily, but more easily to C code than C++. Commented May 6, 2013 at 5:22
  • 7
    If you download a "C++ open source project [...] filled with memory leaks", fix it and submit a patch to the maintainer! Commented May 6, 2013 at 6:09

2 Answers 2

6

One of the most-often heard of approaches is to use Hans Boehm's GC, which can be plugged into C++. Of course, an alternative is to use smart pointers that keep track of the use of objects.

For everybody who upvoted the "who needs this" comment, the answer is that it can be more expensive:

  • Imagine that you fork() your program and now start adjusting refcounters in objects that remain constant otherwise. This will cause performance overhead because it means that the OS can't share the memory between the two processes, i.e. it breaks copy-on-write. In some cases, it can mean that the OS has to swap in memory only to copy and adjust reference counters.
  • Another example is something like the suggested boost::shared_ptr. Each of these has an additional allocation as overhead in order to store the reference counter, weak reference counter and deleter. This doesn't come for free either. Further, an instance thereof has twice the size of a pointer.
  • Then, if you use a normal size_t for the refcounter and built-in increment/decrement, your code isn't multithreading safe. However, if you use atomic integers, incrementing and decrementing takes much more time to flush caches and because it disallows reordering. Remember, every time you copy such a pointer, you have to increment the reference counter. Every time one instance is destroyed, you have to decrement the counter again. Maintaining a reference count can accumulate to much higher overhead that using a mark-and-sweep GC to count references now and then.
  • Lastly, refcounted pointers need the programmer to actively consider the possibility of cycles. GCs can detect and break cycles automatically.

If you keep the above in mind, a GC is an alternative. It does have disadvantages, like non-deterministic cleanup, but Java and C# show that you can live with this and there is nothing that keeps you from programming it yourself in those places where you really need it.

Sign up to request clarification or add additional context in comments.

4 Comments

2nd bullet: std::make_shared avoids the additional allocation, it coalesces the two. This improves locality of reference and reduces fragmentation. This also reduces the penalty of cache flushes, as the object is often flushed alongside its count. (3rd bullet). Of course, if you use fork, this sharing amplifies the COW problem.
@MSalters: Not to mention that the C++ Standard discourages COW (see how they changed std::basic_strings requirements...)
@MFH: That's a completely different kind of COW. It has to copy on a possible write, i.e. after calling the non-const operator[], whereas the page copy happens only on a physical write, blocks only the writing thread, and is optimally (page) aligned.
Actually, if you know a set of objects will be constant after the fork, you can create your own make_shared_fork<T> that keeps all counter in one memory pool and all constant objects in another. That way, the first COW will copy all counters and only the counters.
1

Usually, you can get around fine using RAII and smart pointers (such as shared_ptr and unique_ptr in C++11).

However, if you need garbage collection, look into Boehm's garbage collector. You could overload operator new as following.

enum GCPlacement { NoGC, GC, }; void* operator new(size_t size, GCPlacement gcp) { void* toReturn; if (gcp == GC) toReturn = GC_MALLOC(size); else toReturn = GC_MALLOC_UNCOLLECTABLE(size); if (!toReturn) throw std::bad_alloc(); else return toReturn; } void operator delete(void* p, GCPlacement) { GC_FREE(p); } 

Now, you can allocate garbage collected memory as following:

Object* o = new (GC) Object(); 

If you want, you can also derive certain classes from the gc class provided by boehmgc to indicate these should always be allocated using garbage collection.

C++/CLI is another solution, but be advised that it technically is not C++ (it is an extension of a partial implementation of C++) and it ties you to the Microsoft/.NET platform -- essentially, it's just C# with a C++ syntax.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.