News for hackers. Stuff that matters.
Re:Which language has the brightest future for replacing C: ... by dbaupp on Wednesday November 11, 2015 @05:53AM (#10545957)
It's definitely very important for some domains, but handling OOM "properly" is a really vague/impossible concept for most non-bare-metal programming. Modern operating systems will over-allocate/over-commit memory via virtual memory (so malloc usually succeeds), and kill programs when the physical memory limit is reached, and/or just grind to a halt by swapping.

For instance, I can happily "allocate" 100 terabytes of memory on my laptop (16 GB of RAM, 16 of swap):

  use std::{thread, time};

  fn main() {
      let _v: Vec<Vec<u8>> =
          (0..100_000)
          .map(|_| Vec::with_capacity(1 << 30)) // 1GB each
          .collect();

      thread::sleep(time::Duration::from_secs(10));
  }
Of course, if I actually tried to use much of it, bad things would happen, but the point is the allocations themselves never failed.

Bare-metal programming, like a kernel, will typically use the lower-level `core` part of the standard library, rather than the whole thing (i.e. `std`) because the kernel will be literally providing the interfaces required for most of std-minus-core.

(I think it would be really great if the standard library could be less harsh when an OOM is actually detected, and I suspect it can be tuned in future, but it's not a show-stopper for most tasks.)

Re:Which language has the brightest future for replacing C: ... by quotemstr on Wednesday November 11, 2015 @06:09AM (#10546005)
> handling OOM "properly" is a really vague/impossible concept for most non-bare-metal programming

I strongly disagree. Handling memory allocation failure is trivial: throw an exception. It's also trivial to reserve enough memory to throw an exception. I honestly don't understand people who claim that recovering from OOM is futile because you need to almost always allocate memory to recover: in fact, you almost never do.

> Modern operating systems will over-allocate/over-commit memory

Windows is a very modern operating system and does not overcommit. (To its credit: overcommit is a terrible idea.) Even on overcommit systems, you can exhaust your address space and see allocation failures. No, 64 bits is not actually infinity. No, the whole world is not 64 bit. (Not every program even benefits from being 64 bit --- that's why the x32 ABI exists.)

> point is the allocations themselves never failed.

The resource you're allocating is address space. When you run out of this resource, your allocations will fail. On overcommit systems, you don't allocate commit charge until you access the memory. It's very difficult to explain to people who work exclusively on overcommit systems that "memory" isn't a single resource, but a set of related ones, each of which can be exhausted.

> I think it would be really great if the standard library could be less harsh when an OOM is actually detected

The only reasonable thing to do on OOM failure is throw an exception, like Java and C++ do. Error codes are too cumbersome even if you dress them up and call them "monads" --- a lot of code allocates, so if you used error codes to indicate OOM, you'd have to manually propagate exceptions from almost everywhere) and just panicking or aborting is too brittle, since you can, in fact, successfully recover from allocation failure, persistent folk myths aside.

Now Rust has both Result _and_ panic/catch_panic, which I think is both sad and hilarious, as it's going to lead to decades of confusion over which error reporting mechanism to use in a particular situation. (The Go designers made exactly the same mistake, as did the designers of the old java.io.File interface.)

It's a shame for such a young language to have that kind of baggage already. If Rust's designers hadn't been so stridently anti-exception in the first place, we'd have ended up with a much better language.

Re:Which language has the brightest future for replacing C: ... by dbaupp on Wednesday November 11, 2015 @06:49AM (#10546147)
> Handling memory allocation failure is trivial

The problem I'm talking about is allocation failure and OOM are not the same: handling out-of-memory reliably is a lot more than just checking for NULL in `malloc`, as I demonstrated. There's no guarantee that allocations will fail when they "should" and so you'll only learn that you're beyond reasonable limits when you touch enough pages that the operating system starts killing programs (possibly yours, possibly others), or when the user cannot actually use their computer in any reasonable manner.

> Windows is a very modern operating system and does not overcommit

Yeah definitely, it's why I was sure to mention the problems with swapping (sure, the memory is allocated and usable by the program, but in slow motion; not so great if you actually want to use the computer).

> The resource you're allocating is address space. When you run out of this resource, your allocations will fail. On overcommit systems, you don't allocate commit charge until you access the memory.

Yes, running out of virtual memory is one way for allocations to fail, but, as you say, there's a variety of different systems at play here. Only failure in one of those systems (requesting virtual memory/address space) is handled by checking for `malloc` returning NULL, and so focusing on just that is missing the forest for the trees. Presumably the overall goal is to handle memory exhaustion gracefully, not to check the return value of NULL (which is just one part of the former).

Re:Which language has the brightest future for replacing C: ... by quotemstr on Wednesday November 11, 2015 @06:58AM (#10546177)
That some operating systems lie about resource commitments is no reason not to provide reasonable facilities for reacting to allocation failures. By doing so, you make it harder to write well-behaved programs for systems that don't overcommit --- besides, no system overcommits address space, so malloc can always fail.

It's true that even with reasonable allocation failure reporting on a non-overcommit system, you can use too much memory and make life unpleasant for users without actually seeing allocations fail. Bounding resource use is important regardless. That's an issue of good behavior, however. Even absent good behavior, programs should at least be robust.

One of the reasons overcommit bothers me so much is that infects programming communities with the idea that resource consumption doesn't matter, since if you use too much, you're just going to get a SIGKILL anyway.

Re:Which language has the brightest future for replacing C: ... by mondoshawan on Wednesday November 11, 2015 @08:22AM (#10546514)
If you throw an exception, what would the resulting recovery mode even /be/, aside from clearing out unused memory (never mind that just finding all of your allocations is a nightmare in and of itself)? And how would this actually work in a non GC world where functions can allocate and free at any time -- ie, you are working on a team and can't know the state of every thread, task or chunk of code at once?
Re:Which language has the brightest future for replacing C: ... by quotemstr on Wednesday November 11, 2015 @08:54AM (#10546636)
> If you throw an exception, what would the resulting recovery mode even /be/

Unwind the stack and present an error message or take other appropriate action, just as we would for any other error. By unwinding the stack, we release owned resources, and some of those resources happen to be memory blocks. What makes memory so special?

> just finding all of your allocations is a nightmare in and of itself

Huh? In a non-GC system, if you can't find your allocations, you're leaking memory.

Re:Which language has the brightest future for replacing C: ... by mondoshawan on Wednesday November 11, 2015 @09:27AM (#10546786)
My point about finding the allocations is actually a bit poorly put: not all parts of your program may be ready to release memory it has held without losing user data in the process.

Memory is special insofar as it is a core resource that has so much contention that OOM situations may not be directly because of your application, and recovery may not even be possible without allocation.

I'm slowly coming to realize my argumentative point is losing ground -- this is great! :-)

Re:Which language has the brightest future for replacing C: ... by kibwen on Wednesday November 11, 2015 @06:24AM (#10546050)

  > Now Rust has both Result _and_ panic/catch_panic
The forthcoming facilities for "catching" panics are deliberately hobbled so as to prevent them from being suitable for use as a general-purpose error-handling mechanism. What they're for is fault isolation, most specifically for preventing code from unwinding across a FFI boundary (which would result in undefined behavior).
Re:Which language has the brightest future for replacing C: ... by quotemstr on Wednesday November 11, 2015 @06:29AM (#10546074)
catch_panic doesn't look particularly hobbled to me. Besides, I can insert an "FFI" boundary between any two parts of the program I want, and nothing can stop me. But it's moot: I'm not keen on using a language designed by people who are opposed in principle to exceptions, the cleanest form of error handling around.
Re:Which language has the brightest future for replacing C: ... by kibwen on Wednesday November 11, 2015 @06:45AM (#10546134)
You can read the comments on the original RFC for stabilizing catch support and see that the majority of them revolve around various ways of deliberately handicapping the API: https://github.com/rust-lang/rfcs/pull/1236

It even inspired a followup RFC for the purpose of codifying these restrictions in a brand-new fundamental trait: https://github.com/rust-lang/rfcs/pull/1323

Re:Which language has the brightest future for replacing C: ... by quotemstr on Wednesday November 11, 2015 @06:51AM (#10546152)
Yes, but it's still progress toward the inevitable end result of traditional C++-style exceptions. That's the inevitable end state because the traditional exception model is simply the best one.
Re:Which language has the brightest future for replacing C: ... by kibwen on Wednesday November 11, 2015 @07:38AM (#10546334)

  > the inevitable
It's not inevitable in the slightest. Rust made a conscious effort to avoid exceptions for good reasons, and there's no reason to suspect that Rust will suddenly pivot on its heel in the opposite direction. Despite your attempts to paint this as a slippery slope, the unwinding-halting mechanisms are there to provide a safety net for people writing Rust libraries that expose C ABIs so that library code can fail gracefully without taking down the parent process.

  > the traditional exception model is simply the best one
Citation needed. :P The Rust community has long since embraced Result-based error handling; I don't hear calls for adding exceptions nearly as often as you seem to suspect. As to "inevitability", you'll be sad to learn that Rust plans on adding a mechanism that will enable applications to make panics impossible to catch, by disabling unwinding entirely and translating all panics to outright aborts (some argue that this should even be the default behavior of Rust code, but that won't happen any time soon). And considering that Mozilla disables exceptions entirely in Firefox, I see no reason they would pressure the Rust developers to add exceptions to Rust.

You seem to be taking Rust's approach to error handling far too personally. :P It is not Rust's position that exceptions are a blight that must be scoured from the face of the Earth. It is merely Rust's position that there are easier ways to achieve concise and composable error handling for its intended domain, given Rust's other features and safety mechanisms.

Re:Which language has the brightest future for replacing C: ... by quotemstr on Wednesday November 11, 2015 @07:47AM (#10546375)
> Despite your attempts to paint this as a slippery slope

It is, though. I'm not[1][2] the only one who very much prefers the exceptional model of error handling. Once the ability to catch exceptions exists, people like me are going to write exceptional code.

[1] https://github.com/rust-lang/rfcs/pull/1236#issuecomment-127... [2] https://github.com/rust-lang/rfcs/pull/1236#issuecomment-128...

> > the traditional exception model is simply the best one

> Citation needed. :P

When Java, Python, C++, and Common Lisp all converge on the same thing, maybe that thing has something going for it. Part of my claim is subjective, but I've worked on systems that used everything from abort to error codes to tagged unions to exceptions for error reporting, and I've found the exceptional code by far the easiest to work with.

In exceptional code, I can write foo().bar().qux() even though foo, bar, and qux can all fail, and without any extra syntactic noise.

> by disabling unwinding entirely and translating all panics to outright aborts

I believe that's a mistake: it's a reprise of the -fno-exceptions debacle of the C++ world, where the ecosystem is fragmented due to fundamental disagreements on the correct error handling strategy. You'll get into a situation where some components rely on panics being hard aborts for correctness and other components rely on non-aborting panics for error handling.

> And considering that Mozilla disables exceptions entirely in Firefox, I see no reason they would pressure the Rust developers to add exceptions to Rust.

Rust is probably a fine Servo implementation language. Tellingly, Mozilla also uses an infallible memory allocator. I merely believe that Rust's design choices for allocation failure and error handling lead to it being a losing contender when compared to modern C++ for general-purpose systems programming.

Re:Which language has the brightest future for replacing C: ... by kibwen on Wednesday November 11, 2015 @08:17AM (#10546498)

  > Once the ability to catch exceptions exists, people like 
  > me are going to write exceptional code.
By all means, go ahead. :) Application code is free to do whatever it wants, and godspeed to you. Meanwhile, the restrictions on the catch API will be sufficiently onerous that library authors will continue to favor Result-based error-handling for their public APIs (to say nothing of the fact that some of their users may have opted to turn panics into aborts).

  > You'll get into a situation where some components rely on panics 
  > being hard aborts for correctness and other components rely on 
  > non-aborting panics for error handling.
Indeed, this is precisely why Rust decided to ship 1.0 with unwinding enabled by default, much to the consternation of those who wished unwinding to be excised from the language entirely. The language is defined such that if your personal `unsafe` blocks fail to consider exception safety, you run the risk of undefined behavior and thereby forfeit Rust's guaranteed safety mechanisms: http://doc.rust-lang.org/nightly/nomicon/exception-safety.ht... . Meanwhile, the fact that catching unwinding is all but unusable as anything other than a failsafe of last resort (and even then is only intended to prevent a total abort and/or undefined behavior) means that no library is going to resort to non-aborting panics for error handling, as mentioned previously.
Re:Which language has the brightest future for replacing C: ... by quotemstr on Wednesday November 11, 2015 @08:22AM (#10546519)
> library authors will continue to favor Result-based error-handling for their public APIs

Except for the library authors who opt to write in C++ instead, of course. If you have to deliberately make a feature of your environment difficult to use, you're optimizing for the wrong thing. The Java experience shows that bad programmers will write bad code no matter how many safeguards you try to add to the language, so the only worthwhile "speed bumps" are those that help people who know what they're doing not accidentally shoot themselves in the foot. I cannot imagine an exception-catch block appearing in my code by accident.

Quite a bit of the discussion in the threads you mentioned has to do with flagging code as "requiring review" and adding "speed bumps" for "potentially troublesome" code. That's very worrisome, as it indicates that at least some members of the Rust community favor the Java-esque sandbox model of safety over the safety-catch model.

C++ has many flaws, but at least it never makes me feel like the language designers thought I need to be protected from myself.

Re:Which language has the brightest future for replacing C: ... by kibwen on Wednesday November 11, 2015 @08:39AM (#10546569)

  > the only worthwhile "speed bumps" are those that help 
  > people who know what they're doing not accidentally 
  > shoot themselves in the foot. I cannot imagine an 
  > exception-catch block appearing in my code by accident.
Rust is very much designed to help people who know what they're doing not shoot themselves in the foot. The risk isn't in a catch block appearing in your program by accident, it's the fact that exception safety is an invisible footgun that has potentially severe implications even for code that doesn't believe that it has any reason to concern itself with error handling in the slightest.

(The irony in all this is that Rust's approach can be interpreted as an attempt to return exceptions to their roots by relegating unwinding to exceptional circumstances, as opposed to the routine error-handling solution that they've become in languages that have chosen to embrace exceptions (e.g. Python's egregious `StopIteration` exception for loop termination).)

Re:Which language has the brightest future for replacing C: ... by quotemstr on Wednesday November 11, 2015 @08:45AM (#10546593)
> return exceptions to their roots by relegating them to exceptional circumstances

Python does it right. I've never bought the argument that "exceptions are for exceptional circumstances". If you use error codes for some errors and exceptions for others, all you do is confuse people. The definition of "exceptional error" is subjective, after all.

As far as I can tell, the advice to use "exceptions for exceptional circumstances" originated in C++ circles in the 1990s, when support for exceptions was bad and throws were slow. The thinking was that you could efficiently use error codes for commonly-encountered errors and still get some of the syntactic benefits of using exceptions for rarer errors. Also, if you were using a compiler without exceptions support, you could turn your exceptions into aborts while not aborting just because a file doesn't exist. You can see vestiges of this thinking in the iostreams API.

Somehow, this performance hack morphed into commonly-accepted dogma. I don't accept this dogma. Exceptions are for any situation that a function can't meet its contract. In Python, if an iterator can't supply its next element, it can't satisfy the contract, and the exception tells you why. I don't think there's anything particularly wrong with that.

Re:Which language has the brightest future for replacing C: ... by kibwen on Wednesday November 11, 2015 @08:50AM (#10546613)
I suppose we'll have to agree to disagree, then. :)