C++ vs Java – Delete vs Garbage Collection

cgarbage-collectionjava

Java garbage collection takes care of dead objects on the heap, but freezes the world sometimes. In C++ I have to call delete to dispose a created object at the end of it's life cycle.

This delete seems like a very low price to pay for non-freezing environment. Placing all relevant delete keywords is a mechanical task. One can write a script that would travel through the code and place delete once no new branches use a given object.

So, what are the pros and cons of Java build in vs C++ diy model of garbage collection.


I don't want to start a C++ vs Java thread. My question is different.
This whole GC thing – does it boil down to "just be neat, don't forget to delete objects you have created – and you will not need any dedicated GC? Or is it more like "disposing objects in C++ is really tricky – I spend 20% of my time on it and yet, memory leaks are a common place"?

Best Answer

The C++ object lifecycle

If you create local objects, you don't need to delete them: the compiler generates code to delete them automatically when the object goes out of scope

If you use object pointers and create objects on the free store, then you have to take care of deleting the object when it's no longer needed (as you have described). Unfortunately, in complex software this might be much more challenging than it looks like (e.g. what if an exception is raised and the expected delete part is never reached ?).

Fortunately, in modern C++ (aka C++11 and later), you have smart pointers, such as for example shared_ptr. They reference-count the created object in a very efficient manner, a little bit like a garbage collector would do in Java. And as soon as the object is no longer referenced, the last active shared_ptr deletes the object for you. Automatically. Like garbage collector, but one object at a time and without delay (Ok: you need some extra care and weak_ptr to cope with circular references).

Conclusion: you can nowadays write C++ code without having to worry about memory allocation, and which is as leak-free as with a GC, but without the freeze effect.

The Java object lifecycle

The nice thing is that you don't have to worry about object lifecycle. You just create them and java takes care of the rest. A modern GC will identify and destroy the objects that are no longer needed (including if there are circular references between dead objects).

Unfortunately, due to this comfort, you have no real control of when the object is really deleted. Semantically, the deletion/destruction coincides with the garbage collection.

This is perfectly fine if looking at objects only in terms of memory. Except for the freeze, but these are not a fatality (people are working on this). I'm not Java expert, but I think that the delayed destruction makes it more difficult to identify leaking in java due to references accidentally kept despite objects are no longer needed (i.e. you can't really monitor the deletion of objects).

But what if the object has to control other resources than memory, for example an open file, a semaphore, a system service ? Your class must provide a method to release these resources. And you'll have the responsibility to make sure that this method is called when the resources are no longer needed. In every possible branching path through your code, ensuring it is also invoked in case of exceptions. The challenge is very similar the explicit deletion in C++.

Conclusion: the GC solves a memory management issue. But it doesn't address the the management of other system resources. The absence of "just-in-time" deletion might make resource management very challenging.

Deletion, garbage collection, and RAII

When you can control the deletion of an object and the the destructor that is to be invoked at deletion, you can take benefit of the RAII. This approach views memory only as a special case of resource allocation and links resource management more safely to the object life cycle, thus ensuring tightly controlled usage of resources.