Hacker News new | past | comments | ask | show | jobs | submit login

Good riddance!

So the proposal was sponsored by HP, Symantec and Intel. I was expecting something related to Microsoft and it's ill conceived idea of "Managed C++", but it all boils down to: Hans Boehm.

As surprised as the next guy to find this in C++ standard. ...Again: good riddance.




Garbage Collection is not a bad idea, but, my takeaway is that if you try to bolt it onto a language that didn't have it in its core design, you're gonna have a bad time.


It's rather that with RAII (C++, Rust) you don't need a GC.

Of course, you can still create and operate a GC arena in C++, to manage a data structure or problem area where it makes sense. But why build in into the language, library, runtime if developers don't need it?


I'd also argue that with well used RAII, programs can be written more reliably than in some GC languages as you have finer control over the lifetime of system resources like Windows HANDLES or sockets and can free them on scope destruct with a simple wrapper class.

On .net I'm constantly fiddling with IDispose and checking each object if it needs a 'using' block so I'm not leaking resources.

On long running resource intensive apps, this can make a real difference and I prefer the finer control C++ gives me.


(Well-designed, first-class) GC is still the only system proven to completely remove memory safety issues. Rust comes close, but it's not RAII but the compiler-enforced ownership tracking which allows for this.

C++ is very much proven to be memory unsafe in practice despite the RAII and smart pointers being part of the standard for a decade or more now. Opt-in memory safety basically just means no memory safety.

Of course, this doesn't mean that you can't create memory safe C++ programs. Probably one or two actually exist. But there also exist memory safe C programs and probably somewhere there is some memory safe program written in assembly as well.


> (Well-designed, first-class) GC is still the only system proven to completely remove memory safety issues.

To be pedantic, you need more than a GC for memory safety. Like a language (type system, bounds checks) that forces you to only look only inside the memory being managed. :-)

Also, "for free" memory safety as offered by java's GC doesn't automatically guarantee resource safety. Without RAII, you still need to manage you file handles the old-fashioned manual way.

Beyond that there are safety concerns that where the shared memory model managed by the GC bites you. For example: Rust solves threading issues with move semantics and pinning, guiding programmer away from shared mutable state. Also think of stop-the-world problems inherent with GCs. They can be life threatening in real-time systems.

So: yes it's true that it's difficult to write safe code in C++, and many safety bugs are related to memory. But that doesn't mean that code in a GCed language is inherently safer.


> Also, "for free" memory safety as offered by java's GC doesn't automatically guarantee resource safety. Without RAII, you still need to manage you file handles the old-fashioned manual way

Don’t you think a file handle is a completely different thing than what is normally talked about with memory safety? Can a un-closed handle let you ++ your way into remote code execution? Or reading uninitialized memory?

Regardless, a GC is about trade offs. A GC alleviates the 99% of programming. Thinking about having to close a file resource occasionally, especially since javac will warn you when you don’t, is leagues easier than having to navigate the borrow checker all of the time.

The same goes for concurrent programming. 99.9% of all code written in GC’d languages like Java never go over a thread boundary.


> Don’t you think a file handle is a completely different thing than what is normally talked about with memory safety? Can a un-closed handle let you ++ your way into remote code execution? Or reading uninitialized memory?

Unfreed memory also doesn't let you ++ your way into remote code execution.

Using a file-handle after it's been closed can cause all sorts of issues; and if the underlying file-descriptor is being reused to e.g. write a shell script you can end up in RCE territory as well.


> Using a file-handle after it's been closed can cause all sorts of issue

Is this possible in managed languages like Java? AFAIK you'll get an exception which is a bug and can cause issues, but its not a safety concern.


No, you can get an exception, but that can happen either way (the OS can close the file handler irrespective of what the process does), and is not a safety violation.

The only problem that can happen in managed languages is leaking of file handlers by not manually closing them, leaving it up to the GC, and opening handles faster than they are being closed — this can cause the OS to run out of handlers for the process, terminating it.

But this is not a big issue in practice in my experience, in Javac try-with-resources idiomatically solves this issue.


> To be pedantic, you need more than a GC for memory safety. Like a language (type system, bounds checks) that forces you to only look only inside the memory being managed. :-)

True enough :-)

> Also think of stop-the-world problems inherent with GCs. They can be life threatening in real-time systems.

There are GCs that can work in real-time systems, given enough resources. RAII is also not suitable for real-time systems without much care, so the point is pretty much moot. Real-time systems require a level of attention to timing that no regular programming paradigm enables.

> So: yes it's true that it's difficult to write safe code in C++, and many safety bugs are related to memory. But that doesn't mean that code in a GCed language is inherently safer.

It is very much clear that programming in a GC language is safer than in C++ (or C or assembly) - not safe (the log4j vulnerability comes to mind), but absolutely and certainly safer. Rust has a radically new approach to memory safety that seems to offer similar advantages. It's still a little early (not that much internet-connected Rust-based infrastructure) to say for sure, but so far it does seem to offer similar or better safety guarantees as a GC language.


Java has try-with-resource blocks, though. But scope-based resource scopes are fundamentally limiting and static, it is not a generic solution.

Preventing data races is cool, but it’s again, not a complete solution to the general category of race conditions, which are the real issue - and I’m not sure if there is any general enough system that could prevent it whole-sale. Also, java’s data races are well-defined (while if you mess up some unsafe logic in rust, your program is completely unpredictable from that point).

Hard real time is so special that I don’t see much point bringing it up here — standard Rust/C/whatever is also not fit for that in and of itself. For soft real time, some GCs may be more than fine, the occasional frame drop won’t kill anyone for example.


> (Well-designed, first-class) GC is still the only system proven to completely remove memory safety issues.

This depends on what you mean by "proven", but I don't think I agree. It's pretty easy to demonstrate that RAII without raw pointers and without multithreading is going to be unable to escape its bounds. And for C++ that includes changing the standard library so it doesn't generate pointers without checking, for example vector is entirely capable of enforcing bounds.

But as you say, opting in on a per-object basis is not going to work.


I was saying "proven" more in the sense of "battle-tested": that is, we can point to large systems people actually use which are free of memory errors, written in Java or C# or other GC languages (those with a few more memory safety features, to be fair, such as out-of-bounds checks on all containers and a memory model that doesn't allow partial reads). We don't have a single large C++ system that is free of memory issues (we do have two for C, CompCert and seL4 - but those are not manually written in C, and they took many times more work than equivalent systems without this property). Perhaps some embedded high-safety systems such as embedded medical or avionics devices would qualify, but those are not public so it's hard to be sure.

So yes, theoretically you can build a complex system with a subset of C++ that is safe. Bjarne Stroustrup has explicitly defined such a subset for use in avionics and other military applications, even before many of the more modern C++ features. But there is little proof that this system can actually be successfully be deployed in most organizations.

I'd also note "without multi threading" is such a huge limitation that it immediately moves your proposed system to toy language territory in my book. And even adding shared memory multi-process collaboration (e.g. mmap() ) would not be safe.


> battle-tested

Well not many languages are actually trying to hit the intersection of memory-safe but no-GC, so I think that's a bit too high of a bar.

> So yes, theoretically you can build a complex system with a subset of C++ that is safe. Bjarne Stroustrup has explicitly defined such a subset for use in avionics and other military applications, even before many of the more modern C++ features. But there is little proof that this system can actually be successfully be deployed in most organizations.

It's extremely difficult to deploy a subset of C++ as C++, for sure. I was thinking more about making a new specific language, but C++ could be a base for ease of explanation.

> I'd also note "without multi threading" is such a huge limitation that it immediately moves your proposed system to toy language territory in my book.

That's because I'm speaking about it as a proof of concept. Allowing multithreading is a hard problem, but it's not something that particularly shouts "you need garbage collection", so I leave it as an exercise to the reader.

Add some locks and stuff. There's a lot of ways to do it.


What would be your solution with regard to iterator invalidation?


The simplest one is probably to count the number of iterators and refuse to reallocate when it's more than zero.

Of course, many data structures could be adjusted so that iterators don't need to be invalidated.


RAII gives you only static, scope-based lifetimes. These are not sufficient in itself for every kind of application. With that said, C++ is a low-level language with manual memory management, so you can do whatever, an unused GC is indeed good riddance.


Interesting that GC was originally part of rust and got un-bolted:

http://pcwalton.github.io/_posts/2013-06-02-removing-garbage...




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: