Live data from Hacker News

Real cost of C++ exception vs error-code checking

lazarenko.me

31–40 of 64 posts

Re: Real cost of C++ exception vs error-code checking

#31
post #13

Earlier quoted context omitted.

"modern C++" has changed meanings so many times in the past 10 years that it's not funny anymore. there's always some "modern" solution in C++ that ends up causing more problems, leading to further "modern" solutions that end up... you get my point. some folks have decided to get off the C++ feature treadmill and go back to, well... getting things done with solid languages (e.g. C) instead of learning about the lates…

Hmm, well, I'm relatively young so I guess I missed all those broken promises :P Still, I think the "trying to code like C in C++" point still stands.

Well, if you're ever bored, read this book: http://www.amazon.com/Modern-Design-Generic-Programming-Patt...

Re: Real cost of C++ exception vs error-code checking

#32

Today with terabyte harddrives, gigabytes of RAM and broadband connections, when is the binary size a more important factor than both execution speed and ease of development? Especially when the binary size difference is probably not huge? Shouldn't the advice of this article just be "use exceptions"?

On my current platform (STM32L micro) we'll have 256K flash, 48K RAM, no hard drive. It's very reasonable to use C++ on such a processor but exception handling might not be something you want to pay for.

Re: Real cost of C++ exception vs error-code checking

#33
post #28

Earlier quoted context omitted.

Sure I can use asserts. But I'm as likely to forget the assert() as I am to forget to check the return value. And even if I did: If you consider the faulty main() in the linked article: How would you use assert() there to make sure that result as used after the call to foo() is actually usable? If foo() returns -1 (because any of the calls to divide returned -1) then result is undefined.

You would put an assert inside of the divide function like so: int divide (int x, int y) { defend (y != 0); return x / y; } Now divide is guaranteed to produce a correct result if it's called with correct data. It's up to the caller to make sure the data is correct, or an assert will happen. Just to finish out the example to show how much cleaner asserting is compared to error handling: int foo(void) { volatile int x…

That's a precondition check. While useful (essential), it doesn't cover all "forgot to check an error code" cases.

Re: Real cost of C++ exception vs error-code checking

#34

Today with terabyte harddrives, gigabytes of RAM and broadband connections, when is the binary size a more important factor than both execution speed and ease of development? Especially when the binary size difference is probably not huge? Shouldn't the advice of this article just be "use exceptions"?

Space is time.

From the Gentoo wiki: -Os is very useful for large applications, like Firefox, as it will reduce load time, memory usage, cache misses, disk usage etc. Code compiled with -Os can be faster than -O2 or -O3 because of this. It's also recommended for older computers with a low amount of RAM, disk space or cache on the CPU. But beware that -Os is not as well tested as -O2 and might trigger compiler bugs.

I believe Apple compiles (a lot or all?) of their stuff with -Os.

Anyway C++ exceptions are awful. ;)

Re: Real cost of C++ exception vs error-code checking

#35
post #12
post #8

Earlier quoted context omitted.

Cache sizes have not seen gains proportional to RAM or HDs.

Sure they have. My 486 built in 1993 had 8 KB cache, 4 MB RAM, and a 120 MB HD. My desktop built in 2009 has 2 MB cache, 2 GB RAM, and a 250 GB HD. Okay, the cache has lagged behind by one or three doublings compared to the other storage types. But that's still pretty close to proportional in a world of exponential gains.

I bet that your 1993 486 had 256KB of L2 cache on the motherboard, so from 256KB to 2MB is less than 10 times, for 500 times the RAM and 2000 times the hard disk size.

Re: Real cost of C++ exception vs error-code checking

#36

Today with terabyte harddrives, gigabytes of RAM and broadband connections, when is the binary size a more important factor than both execution speed and ease of development? Especially when the binary size difference is probably not huge? Shouldn't the advice of this article just be "use exceptions"?

On my current platform (STM32L micro) we'll have 256K flash, 48K RAM, no hard drive. It's very reasonable to use C++ on such a processor but exception handling might not be something you want to pay for.

It is not. Unless for trivial things, using C++ for a system with 48KB of RAM is completely non sense (48KB is quite good amount of memory for plain C but not for C++).

Re: Real cost of C++ exception vs error-code checking

#37
post #13

Earlier quoted context omitted.

"modern C++" has changed meanings so many times in the past 10 years that it's not funny anymore. there's always some "modern" solution in C++ that ends up causing more problems, leading to further "modern" solutions that end up... you get my point. some folks have decided to get off the C++ feature treadmill and go back to, well... getting things done with solid languages (e.g. C) instead of learning about the lates…

Hmm, well, I'm relatively young so I guess I missed all those broken promises :P Still, I think the "trying to code like C in C++" point still stands.

A compressed version can be obtained simply by comparing the initial release of C++ to modern C++, and recalling that the initial version of C++ itself shipped with, well, pretty much the same set of promises that modern C++ ships with.

Re: Real cost of C++ exception vs error-code checking

#38

Earlier quoted context omitted.

You would put an assert inside of the divide function like so: int divide (int x, int y) { defend (y != 0); return x / y; } Now divide is guaranteed to produce a correct result if it's called with correct data. It's up to the caller to make sure the data is correct, or an assert will happen. Just to finish out the example to show how much cleaner asserting is compared to error handling: int foo(void) { volatile int x…

That's a precondition check. While useful (essential), it doesn't cover all "forgot to check an error code" cases.

If you're really trying to write efficient code (which is what this article claims to care about) you don't 'forget' to do things like assert that the data is correct. You _guarantee_ that the data is correct and then you process it as fast as you can without having to check.

You only run into trouble with this method if the data verification step is the computationally expensive operation.

Re: Real cost of C++ exception vs error-code checking

#39

Today with terabyte harddrives, gigabytes of RAM and broadband connections, when is the binary size a more important factor than both execution speed and ease of development? Especially when the binary size difference is probably not huge? Shouldn't the advice of this article just be "use exceptions"?

How many hundreds of megabytes or gigabytes is our operating system installation?

Size matters a lot because harddrives are stinkin' snails when compared to CPU and RAM. All that stuff needs to be loaded from somewhere, and while SSD's have changed the scheme a bit, there's still a major gap between storage and memory.

Re: Real cost of C++ exception vs error-code checking

#40
post #21

I assume he was proving a point where main() of his full program using error code checking was not in fact checking the return value of foo() Even in simple example code like this you can forget a check. In this case that result would be undefined if any call to devide failed. I'd much rather have my program blow up with a readable stack trace pointing to where it happened than it working with a basically random valu…

You can accomplish this by using asserts in your code. You don't need exceptions to get a callstack and you can assert that values are valid and force a crash / callstack dump when they're not. On top of that, you can compile the asserts out for release builds if you're confident they won't be hit.

Normally you turn assert() off for production buids, so it's not a robust solution, as some error conditions may not get generated in testing.

The memory protection catches a lot of out-of-bounds memory references pretty well, and if you enable core dumps, you can extract neat backtrace from the core file (provided your routines fail-forward in case of invalid arguments). Moreover, some compilers can be instructed to instrument your code & data, including stack, with guard data, meant to trip process if it accesses wrong memory region. GNU malloc does some guardians if you sest $MALLOC_CHECK_.

If you aren't worried about vendor lock-in, you can use GCC's __attribute__((warn_unused_result)) [1]

--

[1] http://sourcefrog.net/weblog/software/languages/C/warn-unuse...

Post reply on HN