Quote:Original post by SneftelHmm... Offhand, I'd guess that it is impossible for a tail-recursive function to become non-tail-recursive as a result of anything related to exceptions. Got an example?
Imagine a recursive function that instantiates class A near the beginning (but after the noop check), and destroys it again right before the recursive call. A good compiler should be able to work out that A is always destroyed before the next level is called, so all instances of A can be collapsed down to a single hunk of storage (like any other variable in a tail-recurse case.) It doesn't have to plant any stack frame code and is free to generate a loop. And best of all, it may be able to optimize the constructor and destructor of A into a single "(re)init A" code block, depending on what they do. These are small wins individually, but taken together you get somewhere.
But if any point in the function can throw an exception, due to some calls it makes, the compiler is going to have to choose between planting code to remember when A needs to be deconstructed, or just using stack frames and deconstructors normally. The latter is likely to be simpler, compilers are already good at that. A brilliant optimizer might do well here, but such brilliance is not common.
I saw that behaviour out of (if failing memory serves; I've used a lot of compilers over the years) gcc on Solaris a number of years ago, and I got around it by recoding for iteration manually, and some refactoring. It was a rare case, but it stuck with me. Bookkeeping costs space or time, usually both. Exceptions require bookkeeping.
Quote:Blame C++'s milquetoasty exception specifiers.
I do. I don't object to exceptions in Java (in fact, it's hard to imagine Java without them.)
Quote:Quote:It leads people to think of the error handling as a sort of afterthoughtHow so?
I've seen this done in commercial code: "Damn, we've got a bug and it's crashing the server. And we have to release. Just put a catch(...) near the beginning and we'll call it fixed."
I was called in to review the code, and I hit the ceiling. First of all the code was supposed to be portable, and using ... to handle bad pointers is not portable. Secondly, the whole mentality of "if we screw up, exception handling will save us" told me we had an education problem. Management didn't see the problem - the crash had been fixed, right? But this server dealt with personal information, and evidence of memory problems in the code was a nightmare scenario to anyone with an actual conscience.
I looked at other code, under new development. The developers who had saved the day with the catch statement had turned proactive - now they were adding catch (...) to all new code, right at the start. Problems? What problems? And they'd gotten fond of throw, as well, but not so fond of smart pointers... Exceptions made all that nasty thinking and checking and worrying about handling error go away. The code looks so much simpler without error paths! And no more crashes! Just some occasional wrong answers that QA didn't always catch! They were productive now!
Those developers were not happy with me - I forced them to stop masking problems and write actual working code. Management was not fond of me: I was Making Scary Noises and causing rework when all they wanted was a lower bug count by yesterday.
I realize that exceptions can be used well. I realize that part of the problem is C++, and they work better in Java. But my experience in the commercial world is that management wants to hire cheap and not hear about problems, and that leads to certain coding styles. So I've learned not to teach styles that lead people into temptation. Especially not now that I work on software with the possibility of mishandled error=human fatality.
Quote:Actually, the runtime cost of the bookkeeping when exceptions are not thrown pretty much IS a free lunch. You should read up on DWARF-2. It's pretty clever how it works.
It is. I look forward to working in an environment where the code (some of it ported to several different platforms) is compiled on systems that are up to date enough to all provide it reliably. Another decade, I figure. In the meantime, for that reason and others, we do not use exceptions in our real-time, safety critical, high speed, portable code.