Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

Well, I know that there are things like malloc/free for C, and new/using-a-destructor for memory management in C++, but I was wondering why there aren't "new updates" to these languages that allow the user to have the option to manually manage memory, or for the system to do it automatically (garbage collection)?

Somewhat of a newb-ish question, but only been in CS for about a year.

share|improve this question

closed as too broad by gnat, durron597, Mason Wheeler, MichaelT, Ixrec Sep 7 '15 at 6:52

There are either too many possible answers, or good answers would be too long for this format. Please add details to narrow the answer set or to isolate an issue that can be answered in a few paragraphs.If this question can be reworded to fit the rules in the help center, please edit the question.

We've got a module in iPhone development this semester. After coding apps for Android for 2 years, this question struck most of the class pretty hard. Only now do we see how many hours Java has actually saved us in not having to track down nasty memory management errors and not having to write boiler plate code. – siamii Oct 8 '11 at 23:28
@NullUserException, since it doesn't specify a way to reclaim memory that pretty much implies a GC. – Winston Ewert Oct 9 '11 at 4:48
@bizso09: Did you look at ARC yet? No need for slow/fat/non-deterministic GC when you've got system-support for reference counting: – JBRWilkinson Oct 10 '11 at 12:01
The answers to this pretty good question are full of religious bullshit. – abatishchev Apr 6 '15 at 3:47

16 Answers 16

up vote 61 down vote accepted

Garbage collection requires data structures for tracking allocations and/or reference counting. These create overhead in memory, performance, and the complexity of the language. C++ is designed to be "close to the metal", in other words, it takes the higher performance side of the tradeoff vs convenience features. Other languages make that tradeoff differently. This is one of the considerations in choosing a language, which emphasis you prefer.

That said, there are a lot of schemes for reference counting in C++ that are fairly lightweight and performant, but they are in libraries, both commercial and open source, rather than part of the language itself. Reference counting to manage object lifetime is not the same as garbage collection, but it addresses many of the same kinds of issues, and is a better fit with C++'s basic approach.

share|improve this answer
A secondary issue is the GC is non-deterministic. The object may or may not still be in memory long after the program has "dropped" it. Refcount lifecycles are deterministic, when the last reference is dropped, the memory is dropped. This has implications not only for memory efficiency, but for debugging as well. A common programming error is the "zombie" object, reference memory that has theoretically been dropped. GC is much more likely to mask this effect, and produce bugs that are intermittent and extremely difficult to track down. – kylben Oct 8 '11 at 22:17
- modern gc's neither track allocations or count references. They build a graph from everything currently on the stack and just condense and wipe everything else (simplified), and GC normally results in reduced language complexity. Even the performance benefit is questionable. – Joel Coehoorn Oct 9 '11 at 0:56
Er, @kylben, the whole point of having automatic GC baked into the language is that it becomes impossible to reference zombie objects, because the GC only frees objects that are impossible to reference! You get the sort of hard-to-track bugs you're talking about when you make mistakes with manual memory management. – Ben Oct 9 '11 at 1:08
-1, GC does not count references. Plus, depending of your memory usage and allocation scheme, a GC can be faster (with an overhead in memory usage). So the argument about performance is fallacy too. Only the close to the metal is a valid point actually. – deadalnix Oct 9 '11 at 2:07
Neither Java nor C# use reference counting: GC schemes based on reference counting are pretty primitive in comparison and perform much worse than modern garbage collectors (mainly because they need to do memory writes to alter reference counts whenever you copy a reference!) – mikera Oct 9 '11 at 2:59

Strictly speaking, there is no memory management at all in the C language. malloc() and free() are not keywords in the language, but just functions that are called from a library. This distinction may be pedantic now, because malloc() and free() are part of the C standard library, and will be provided by any standard compliant implementation of C, but this wasn't always true in the past.

Why would you want a language with no standard for memory management? This goes back to C's origins as 'portable assembly'. There are many cases of hardware and algorithms that can benefit from, or even require, specialized memory management techniques. As far as I know, there is no way to completely disable Java's native memory management and replace it with your own. This is simply not acceptable in some high performance/minimal resource situations. C provides almost complete flexibility to choose exactly what infrastructure your program is going to use. The price paid is that the C language provides very little help in writing correct, bug free code.

share|improve this answer
+1 one for the overall good answer, but also especially for "The price paid is that the C language provides very little help in writing correct, bug free code" – Shivan Dragon Jul 13 '13 at 11:46

Because, when using the power of C++, there is no need.

Herb Sutter: "I've haven't written delete in years."

see Writing modern C++ code: how C++ has evolved over the years 21:10

It may surprise many experienced C++ programmers.

share|improve this answer
interesting video. 21 minutes in, and 55 minutes in were the best bits. Too bad the WinRT calls still looked to be C++/CLI bumpf. – gbjbaanb Oct 8 '11 at 23:39
@dan04: That's true. But then, if you write in C, you get what you ask for. – DeadMG Oct 14 '11 at 9:16
Managing the smart pointers is not any more demanding than making sure you don't have unnecessary references in a garbage collected environment. Because GC can't read your mind, it's not magic either. – Tamás Szelei Oct 14 '11 at 11:56

The real answer is that the only way to make a safe, efficient garbage collection mechanism is to have language-level support for opaque references. (Or, conversely, a lack of language-level support for direct memory manipulation.)

Java and C# can do it because they have special reference types that cannot be manipulated. This gives the runtime the freedom to do things like move allocated objects in memory, which is crucial to a high-performance GC implementation.

For the record, no modern GC implementation uses reference counting, so that is completely a red herring. Modern GCs use generational collection, where new allocations are treated essentially the same way that stack allocations are in a language like C++, and then periodically any newly allocated objects that are still alive are moved to a separate "survivor" space, and an entire generation of objects is deallocated at once.

This approach has pros and cons: the upside is that heap allocations in a language that supports GC are as fast as stack allocations in a language that doesn't support GC, and the downside is that objects that need to perform cleanup before being destroyed either require a separate mechanism (e.g. C#'s using keyword) or else their cleanup code runs non-deterministically.

Note that one key to a high-performance GC is that there must be language support for a special class of references. C doesn't have this language support and never will; because C++ has operator overloading, it could emulate a GC'd pointer type, although it would have to be done carefully. In fact, when Microsoft invented their dialect of C++ that would run under the CLR (the .NET runtime), they had to invent a new syntax for "C#-style references" (e.g. Foo^) to distinguish them from "C++-style references" (e.g. Foo&).

What C++ does have, and what is regularly used by C++ programmers, is smart pointers, which are really just a reference-counting mechanism. I wouldn't consider reference counting to be "true" GC, but it does provide many of the same benefits, at the cost of slower performance than either manual memory management or true GC, but with the advantage of deterministic destruction.

At the end of the day, the answer really boils down to a language design feature. C made one choice, C++ made a choice that enabled it to be backward-compatible with C while still providing alternatives that are good enough for most purposes, and Java and C# made a different choice that is incompatible with C but is also good enough for most purposes. Unfortunately, there is no silver bullet, but being familiar with the different choices out there will help you to pick the correct one for whatever program you're currently trying to build.

share|improve this answer
This is the actual answer to the question – coredump Sep 6 '15 at 7:11

"All" a garbage collector is is a process that runs periodically checking to see if there are any unreferenced objects in memory and if there are deletes them. (Yes, I know this is a gross oversimplification). This is not a property of the language, but the framework.

There are garbage collectors written for C and C++ - this one for example.

One reason why one hasn't been "added" to the language could be because of the sheer volume of existing code that would never use it as they use their own code for managing memory. Another reason could be that the types of applications written in C and C++ don't need the overhead associated with a garbage collection process.

share|improve this answer
But future programs written would begin to use the garbage collector, no? – Dark Templar Oct 8 '11 at 21:07
While garbage collection is theoretically independent from any programming language, it is pretty hard to write a useful GC for C/C++, and even impossible to make a fool-proof one (at least as foolproof as Java's) - the reason Java can pull it off is because it runs in a controlled virtualized environment. Conversely, the Java language is designed for GC, and you'll have a hard time writing a Java compiler that doesn't do GC. – tdammers Oct 8 '11 at 21:55
@tdammers: I agree that garbage-collection needs to be supported by the language to be possible. However, the main point is not virtualization and controlled environment, but strict typing. C and C++ are weakly typed, so they allow things like storing pointer in integer variable, reconstructing pointers from offsets and such things that prevent the collector from being able to tell reliably what is reachable (C++11 prohibits the later to allow at least conservative collectors). In Java you always know what is a reference, so you can collect it precisely, even if compiled to native. – Jan Hudec Oct 10 '11 at 7:50
@ThorbjørnRavnAndersen: I can write a valid C program that stores pointers in such a way that no garbage collector could ever find them. If you then hook a garbage collector to malloc and free, you would break my correct program. – Ben Voigt Oct 15 '11 at 3:52
@ThorbjørnRavnAndersen: No, I wouldn't call free until I was done with it. But your proposed garbage collector that doesn't free the memory until I explicitly call free isn't a garbage collector at all. – Ben Voigt Oct 16 '11 at 14:47

C was designed in an era when garbage collection was barely an option. It was also intended for uses where garbage collection would not generally work - bare metal, real time environments with minimal memory and minimal runtime support. Remember that C was the implementation language for the first unix, which ran on a pdp-11 with 64*K* bytes of memory. C++ was originally an extension to C - the choice had already been made, and it's very hard to graft garbage collection onto an existing language. It's the kind of thing that has to be built in from the ground floor.

share|improve this answer

I don't have the exact quotes but both Bjarne and Herb Sutter says something along the lines:

C++ doesn't need a garbage collector, because it has no garbage.

In modern C++ you use smart pointers and therefore have no garbage.

share|improve this answer
what are smart pointers? – Dark Templar Oct 8 '11 at 21:03
if it was that simple, nobody would have implemented any GC. – deadalnix Oct 9 '11 at 2:15
@deadalnix: Right, because nobody ever implements anything overly complicated, slow, bloated, or unnecessary. All software is 100% efficient all the time, right? – Zach Oct 9 '11 at 5:54
@deadalnix - The C++ approach to memory management is newer than garbage collectors. RAII was invented by Bjarne Stroustrup for C++. Destructor cleanup is an older idea, but the rules for ensuring exception-safety are key. I don't know when exactly when the idea itself was first described but the first C++ standard was finalized in 1998, and Stroustrups "Design and Evolution of C++" wasn't published until 1994, and exceptions were a relatively recent addition to C++ - after the publication of the "Annotated C++ Reference Manual" in 1990, I believe. GC was invented in 1959 for Lisp. – Steve314 Oct 15 '11 at 12:25
@deadalnix - are you aware that at least one Java VM used a reference-counting GC that could (almost) be implemented using C++-style RAII using a smart pointer class - precisely because it was more efficient for multithreaded code than existing VMs? See One reason you don't see this in C++ in practice is the usual GC collection - it can collect cycles, but can't choose a safe destructor order in the presence of cycles, and thus cannot ensure reliable destructor cleanup. – Steve314 Oct 15 '11 at 14:10

You ask why these languages haven't been updated to include an optional garbage collector.

The problem with optional garbage collection is that you can't mix code that uses the different models. That is, if I write code that assumes you are using a garbage collector you can't use it in your program which has garbage collection turned off. If you do, it'll leak everywhere.

share|improve this answer

There's various issues, including...

  • Although GC was invented before C++, and possibly before C, both C and C++ were implemented before GCs were widely accepted as practical.
  • You can't easily implement a GC language and platform without an underlying non-GC language.
  • Although GC is demonstrably more efficient than non-GC for typical applications code developed in typical timescales etc, there are issues where more development effort is a good trade-off and specialized memory management will outperform a general-purpose GC. Besides, C++ is typically demonstrably more efficient than most GC languages even without any extra development effort.
  • GC is not universally safer than C++-style RAII. RAII allows resources other than memory to be automatically cleaned up, basically because it supports reliable and timely destructors. These cannot be combined with conventional GC methods because of issues with reference cycles.
  • GC languages have their own characteristic kinds of memory leaks, particularly relating to memory that will never be used again, but where existing references existed that have never been nulled out or overwritten. The need to do this explicitly is no different in principle than the need to delete or free explicitly. The GC approach still has an advantage - no dangling references - and static analysis can catch some cases, but again, there's no one perfect solution for all cases.

Basically, partly it's about the age of the languages, but there will always be a place for non-GC languages anyway - even if it is a bit of a nichey place. And seriously, in C++, the lack of GC isn't a big deal - your memory is managed differently, but it isn't unmanaged.

Microsofts managed C++ has at least some ability to mix GC and non-GC in the same application, allowing a mix-and-match of the advantages from each, but I don't have the experience to say how well this works in practice.

Rep-whoring links to related answers of mine...

share|improve this answer

The short and boring answer to this question is that there needs to be a non-garbage collected language out there for the people that write the garbage collectors. It's not conceptually easy to have a language that at the same time allows for very precise control over the memory layout and has a GC running on top.

The other question is why C and C++ don't have garbage collectors. Well, I know C++ has a couple of them around but they aren't really popular because they are forced to deal with a language that wasn't designed to be GC-ed in the first place, and the people that still use C++ in this age aren't really the kind that misses a GC.

Also, instead of adding GC to an old non-GC-ed language, it is actually easier to create a new language that has most of the same syntax while supporting a GC. Java and C# are good examples of this.

share|improve this answer
Somewhere on or SO, there's a claim someone made to me that someone was working on a self-bootstrapping garbage-collected thingy - IIRC basically implementing the VM using a GC language, with a bootstrapping subset used to implement the GC itself. I forget the name. When I looked into it, it turned out that they'd basically never achieved the leap from the subset-without-GC to the working-GC level. This is possible in principle, but AFAIK it has never been achieved in practice - it's certainly a case of doing things the hard way. – Steve314 Oct 15 '11 at 1:52

Can you imagine writing a device handler in a language with garbage collection? How many bits could come down the line while the GC was running?

Or an operating system? How could you start the garbage collection running before you even start the kernel?

C is designed for low level close to the hardware tasks. The problem? is it is such a nice language that its a good choice for many higher level tasks as well. The language czars are aware of these uses but they need to support the requirements of device drivers, embedded code and operating systems as a priority.

share|improve this answer
C good for high level? I snorted my drink all over my keyboard. – DeadMG Oct 14 '11 at 9:18
Well, he did say "many higher level tasks". He could be troll-counting (one, two, many...). And he didn't actually say higher than what. Jokes aside, though, it's true - the evidence being that many significant higher-level projects have been successfully developed in C. There may be better choices now for a lot of those projects, but a working project is stronger evidence than speculation about what might have been. – Steve314 Oct 15 '11 at 3:11

Garbage collection is fundamentally incompatible with a systems language used for developing drivers for DMA-capable hardware.

It's entirely possible that the only pointer to an object would be stored in a hardware register in some peripheral. Since the garbage collector wouldn't know about this, it would think the object was unreachable and collect it.

This argument holds double for compacting GC. Even if you were careful to maintain in-memory references to objects used by hardware peripherals, when the GC relocated the object, it wouldn't know how to update the pointer contained in the peripheral config register.

So now you'd need a mixture of immobile DMA buffers and GC-managed objects, which means you have all the disadvantages of both.

share|improve this answer
Not if there's a clear divide between the high-level code which is all GC, and the low-level code that opts out of GC. I mainly developed the idea while looking at D some years ago, which allows you to opt out of GC but doesn't allow you to opt back in. Take for example a B+ tree library. The container as a whole should be GC, but the data structure nodes probably not - it's more efficient to do a customized scan through the leaf nodes only than to make the GC do a recursive search through the branch nodes. However, that scan does need to report the contained items to the GC. – Steve314 Oct 15 '11 at 13:53

Because, C & C++ are relatively low level languages meant for general purpose, even, for example, to run on a 16-bit processor with 1MB of memory in an embedded system, which couldn't afford wasting memory with gc.

share|improve this answer
"Embedded system"? At the time C was standardized (1989), it needed to be able to handle PCs with 1 MB of memory. – dan04 Oct 17 '11 at 7:35

There are garbage collectors in C++ and C. Not sure how this works in C, but in C++ you can leverage RTTI to dynamically discover your object graph and use that for garbage collection.

To my knowledge, you cannot write Java without a garbage collector. A little search turned up this.

The key difference between Java and C/C++ is that in C/C++ the choice is always yours, whereas in Java you're often left without options by design.

share|improve this answer

It's a trade off between performance and safety.

There is no guarantee that your garbage will be collected in Java, so it may be hanging around using up space for a long time, while the scanning for unreferenced objects (ie garbage) also takes longer than explicitly deleting or freeing an unused object.

The advantage is, of course, that one can build a language without pointers or without memory leaks, so one is more likely to produce correct code.

There can be a slight 'religious' edge to these debates sometimes - be warned!

share|improve this answer

Here is a list of inherent problems of GC, which make it unusable in a system language like C:

  • The GC has to run below the level of the code whose objects it manages. There is simply no such level in a kernel.

  • A GC has to stop the managed code from time to time. Now think about what would happen if it did that to your kernel. All processing on your machine would stop for, say, a millisecond, while the GC scans all existing memory allocations. This would kill all attempts to create systems that operate under strict real-time requirements.

  • A GC needs to be able to distinguish between pointers and non-pointers. That is, it must be able to look at every memory object in existence, and be able to produce a list of offsets where its pointers can be found.

    This discovery must be perfect: The GC must be able to chase all the pointers it discovers. If it dereferenced a false positive, it would likely crash. If it failed to discover a false negative, it would likely destroy an object that's still in use, crashing the managed code or silently corrupting its data.

    This absolutely requires that type information is stored in every single object in existence. However, both C and C++ allow for plain old data objects which contain no type information.

  • GC is an inherently slow business. Programmers that have been socialized with Java may not realize this, but programs can be orders of magnitude faster when they are not implemented in Java. And one of the factors that make Java slow is GC. This is what precludes GCed languages like Java from being used in supercomputing. If your machine costs a million a year in power consumption, you don't want to pay even 10% of that for garbage collection.

C and C++ are languages that are created to support all possible use cases. And, as you see, many of these use cases are precluded by garbage collection. So, in order to support these use cases, C/C++ cannot be garbage collected.

share|improve this answer

protected by gnat Sep 6 '15 at 13:39

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site.

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.