Practicality of a C++ Garbage collector

Started by
15 comments, last by Melkon 8 years, 3 months ago

Garbage collectors are usually pretty well designed to do what they do, but the problem is that they really are just overkill as a core subject. You're talking about having an entire extra layer of code between you and the machine that does nothing except try to guess how you want to use memory and when you want it released. Or even try to second guess you because you may not actually have a clue of when things should be released. I'm not saying garbage collectors are bad or not useful, it certainly is a constant that programmers make mistakes, but in a way that's the big flaw, its a construct that tries to make up for you making mistakes.

It is kind of a cost benefit thing though, coding can feel much more smooth and intuitive(and less work) in languages with more automatic features than C++. But if that's what is important to you then you should probably be coding in that language, C++ is usually used specifically because it is so bare metal and offers freedom of choice.

Advertisement

You should watch both keynotes from CppCon on the ownership annotations in the C++ Core Guidelines and accompanying support library.

I appreciate that at first glance garbage collection seems like a good idea (and many others have been suckered in before), but in the end it's almost always detrimental as compared to actually knowing the lifetimes and ownership of your memory allocations. Actually knowledge (where available) is always better than heuristics.

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

I'm late to responding to this. Busy with the holidays and whatnot...


So far, I have not found a use for std::unique_ptr, although I am sure there exist valid use cases.

This. Is. Terrifying.

Code should not be littered with shared_ptr everywhere (as function parameters, etc.). These classes are about ownership. If a function is going to run a few operations on a given pointer, it should be accepting a T*, not a shared_ptr. Your goto container should be unique_ptr. Only when you discover you have 2+ actual resource managers that need to monitor a particular instance should you reach shared_ptr/weak_ptr. In short, if you have "not found a use for unique_ptr", you're doing something wrong.

Amateurs practice until they do it right.Professionals practice until they never do it wrong.

There is also std::unique_ptr and friends for your exclusive ownership links that move around. So far, I have not found a use for std::unique_ptr, although I am sure there exist valid use cases.

Say what? std::unique_ptr is the default-to for replacing this:


class B
{
};

class A
{
public:

    A(void) : m_pB(nullptr)
    {    
    }

    ~A(void)
    {
        delete m_pB;
    }

    void MakeB(void)
    {
        delete m_pB;
        m_pB = new B;
    }

private:

    B* m_pB;

};

with that:


class B
{
};

class A
{
public:

	void MakeB(void)
	{
		m_pB = std::make_unique<B>();
	}

private:

	std::unique_ptr<B> m_pB;
};

So pretty much whenever you would request dynamic memory and do not absolutely require reference counting, you use unique_tr. This makes code so much simpler, easier to read, safer to reason about, safer, etc...

This. Is. Terrifying.

Code should not be littered with shared_ptr everywhere (as function parameters, etc.). These classes are about ownership. If a function is going to run a few operations on a given pointer, it should be accepting a T*, not a shared_ptr. Your goto container should be unique_ptr. Only when you discover you have 2+ actual resource managers that need to monitor a particular instance should you reach shared_ptr/weak_ptr. In short, if you have "not found a use for unique_ptr", you're doing something wrong.
Haha :D

No worries, I don't use shared pointers much, not sure I ever used weak pointers at all, if I have it's one time only, for some cache or so :)

I never use unique_ptr, since a data member is way much simpler:


class A { ... };

class B {
public:
    A a;
};

@Alberth Agreed. Avoiding the pointers entirely is the best. :D

Amateurs practice until they do it right.Professionals practice until they never do it wrong.

I never use unique_ptr, since a data member is way much simpler:

class A { ... };class B {public:    A a;};
But this pattern is not always possible or desirable.

As Stroustrup said, C++ doesn't have Garbage collector, because C++ doesn't generate garbage. smile.png

GC is problematic:

- It gives you the illusion that you shouldn't care about resource management. In real world you still have to (it's more of a beginner trap)

- There are alot of resource type (eg.: memory, files, locks, threads etc), but GC only care about memory.

- It's memory management is also poor, as long as you care about performance it's never acceptable.

- If you doesn't develop performance critical applications GC can be viable, but when you touch C++ you mostly really care about performance.

As long as you write idiomatic C++ code it's impossible to leak anything. What you don't use is released instantly.

The solution is simple:

- Never allocate directly any (non-thread) resource. So never write: new, delete, lock, unlock, open, close etc.

- Use resource handlers -> you will end up with an exception safe code without writing try-catch blocks everywhere.

- The best is if your static analyzer drop you warnings about resource allocation or release.

This topic is closed to new replies.

Advertisement