Live data from Hacker News

Current hardware trends make C++ exceptions harder to justify

open-std.org

361–370 of 516 posts

Re: Current hardware trends make C++ exceptions harder to justify

#361
post #167

Earlier quoted context omitted.

More people start using C++ professionally in any given week that the sum total paid to code Rust. Rust is not "displacing" C++ anywhere beyond the HN echo chamber.

We've talked about Rust in my monthly beering meetings with other programmers, so it's definitely gaining mindshare to some extend. And it's being prepped for Linux kernel inclusion. Once that lands it will be pretty respectable.

In other words, talk. Like on HN. Respectable doesn't mean used.

Re: Current hardware trends make C++ exceptions harder to justify

#362
post #191

I find this paper quite unconvincing. Exceptions are exceptional so in principle it doesn't matter (within reason) how long it takes to throw one as long as it costs nothing not to do so. So measuring the cost of repeated throws IMHO doesn't cast light on any useful case, and the approaches that add runtime cost for the path not taken, even Herb Sutter's, are not acceptable. His code transformation example is simply…

The problem is that in many practical situations you don’t know which situation is “exceptional”. If you write a jpeg-processing service, it’s intuitive to raise an exception on a malformed jpeg, but there’s no guarantee that only 1% of the jpegs users upload to the service are malformed. In other words, we treat exceptions as exceptions from our code expects , not what’s statistically unlikely in the input space, wh…

This is a bit of a stretch. The purpose of the service has to be processing jpegs where they are expected to be bad. Moreover, they have to be mostly bad; i.e. the service is specifically intended for finding rare good jpegs in a deluge of bad ones, as quickly as possible.

In a situtaion where are more bad jpegs than good ones, we still don't necessarily care that they cause the slow path, if the purpose of the service is doing meaningful processing with good jpegs.

Re: Current hardware trends make C++ exceptions harder to justify

#363

Earlier quoted context omitted.

Except you are not supposed to throw in a destructor.

https://www.cs.technion.ac.il/users/yechiel/c++-faq/dtors-sh... but what if dtor fails(e.g. can't release a resource), is the by-default action terminate or ignore?

Well, the "environment" may decide for you in some cases, but there is no default action as such. You log an error and either terminate or ignore - depending on which causes less harm.

Re: Current hardware trends make C++ exceptions harder to justify

#364

Earlier quoted context omitted.

Well that's unfortunate. I suspect the fault lies with C, the early versions of which did not have the 'void' keyword, and 'int' was assumed as the default return type - which also meant that when such "function" did not include a 'return' statement it "returned" whatever garbage was left in the register. Instead of adding the keyword 'void' (to be abused later as the empty arg list) they could have added 'proc' inst…

> Well that's unfortunate How so?

Because procedures are a fact of life, not some "bad design." (And the need for the void "return type" in C is just a recognition of that fact.)

Re: Current hardware trends make C++ exceptions harder to justify

#365

Earlier quoted context omitted.

Your opinion being that you should not use exceptions in that type of case. In which cases should you use exceptions?

When something happens that violates your assumptions about your own program's behavior, throwing it into a state where it doesn't know what happens next. Kind of like a panic.

So, CPU exceptions such as a "page not present" TLB fault should not be used to implement virtual memory.

Re: Current hardware trends make C++ exceptions harder to justify

#366

Earlier quoted context omitted.

Logging can be done but I can't see how you could handle errors. If I'm processing 10 transactions and transaction 8 fails, needs to be retried a couple of times before being skipped for 9, I don't know how you'd do that other than going up the stack to where you're looping over the transaction list.

Not everything is a transaction; and not all transactions are processed serially in non-overlappend time slices. Most systems will process multiple pieces of work concurrently (and can't just throw a new OS thread at each of them). The implication is that you can't just back out of a call stack like in a quickly hacked-up script. Stack frames aren't containers for whole transactions. Rather, pieces of work are tracke…

Languages with async/await and exceptions have already solved this.

Re: Current hardware trends make C++ exceptions harder to justify

#367
post #296

Earlier quoted context omitted.

If you read the article by Anders Hejlsberg, he's not arguing against centralized handling of exceptions—the handling of runtime exceptions is expected to be centralized near the main program loop. That, however, is a general-purpose handler which won't have much logic related to any particular kind of exception; it just reports what happened and moves on. You don't need checked exceptions for that. The condition sys…

Fair. Sounds like you are more claiming that most functions would be better returning a result type, but some will be better with more? I view this as I want my engine to mostly just work. It may need to indicate "check engine" sometimes, though. And that, by necessity, has to be a side channel? I think that is my ultimate dream. I want functions to have a side channel to the user/operator that is not necessarily in…

> I want functions to have a side channel to the user/operator that is not necessarily in the main flow path.

That is the essence of the Common Lisp condition system, and you can get there in most languages with closures, or at least function pointers, and exceptions or some other non-local return mechanism using a combination of callback functions for the conditions and unchecked exceptions for the default, unhandled case. The key is that you don't try to catch the exceptions, except at the top level where they are simply reported to the user. Instead you register your condition handler as a callback function so that it will be invoked to resolve the issue without unwinding the stack. It helps to have variables with dynamically-scoped values for this, though you can work around the absence of first-class support as long as you have thread-local storage.

C++ actually uses this model for its out-of-memory handling. You can register a callback with std::set_new_handler() to be invoked if memory allocation with `operator new` fails; if it returns then allocation is retried, and only if there is no handler is an exception thrown. Unfortunately this approach didn't really catch on in other areas.

Re: Current hardware trends make C++ exceptions harder to justify

#368

Earlier quoted context omitted.

It's also easy to provide a default factory: https://doc.rust-lang.org/std/default/trait.Default.html

True, but the naming does matter. Calling Thing::default() clearly communicates that your just getting baseline values and not a lot of magical other initialization stuff going on— with a Thing::Thing() in C++, you're really at the mercy of whatever the project conventions are for how "fat" the constructor is going to be. I think the naming is also important for cases where there are potentially multiple reasonable d…

> Calling Thing::default() clearly communicates that your just getting baseline values and not a lot of magical other initialization stuff going on— with a Thing::Thing() in C++, you're really at the mercy of whatever the project conventions are for how "fat" the constructor is going to be.

In C++ the constructor without arguments is called default constructor. Of course the expectations depend on conventions, but usually it's something from uninitialized garbage to an empty state.

Re: Current hardware trends make C++ exceptions harder to justify

#369
post #288

Earlier quoted context omitted.

"exceptions are exceptional" means what?

The reason they care called "exceptions" is they are not part of the normal behavior of the function (/block, algorithm) and aren't something that can be handled locally. Something that is exceptional is unusual, out of the typical scope of things. In English there is a phrase, "the exception to the rule" -- because the rule is what normally happens. So if you are trying to hold a lock you don't throw an exception, y…

English also has the phrase "the exception proves the rule" - and it's just swell when our general code handles special cases.

I would have not have thought an unreachable host was exceptional, given that it's quite normal.

Re: Current hardware trends make C++ exceptions harder to justify

#370
post #321

Earlier quoted context omitted.

> But there's a design pattern where nearly everything is returned as an exception. It's the normal path in some code. The problem isn’t that C++ exceptions are slow when used the way the compiler expects. The problem is a mismatch between how C++ expects you to use the feature, and how people are actually using the feature. I can’t find the story now, but I read about this happening with Ruby on Rails. Someone dug i…

I think, given a language that supports elegantly catching exceptions, it is inevitable that things like that will be written. And why not? The language makes them nice to write, which signals to users that it is something you should be using a lot. I think the approach Go, Rust and others take there is the right way to go. By making panics annoying or even impossible to recover from in some cases, they ensure that t…

> it is inevitable that things like that will be written. And why not?

We can't just blame the programming language for programmers not understanding how computers work.

I think as computers have gotten faster, and languages higher level, we've stopped talking about computers as mechanical devices. And this is a really important perspective to have.

Can you answer these questions about your program?

- How big is your binary / JS bundle? What parts take up most of the space?

- When your program runs, what does the computer spend most of its time executing? What parts of your program are the slowest, and why?

- How big is the memory footprint? Which parts of your program use the most RAM?

For binary programs (like rust / Go / C), which patterns are easier or harder for the optimizer?

If there are two ways to design your code, how do you discover which approach will run faster?

This stuff shouldn't be considered advanced concepts. An architect understands the building they've designed. A chef knows what their food tastes like. When you program, you're making a thing. You should understand what you made and how it will be executed on the computer.

Post reply on HN