I have read this blog post, this documentation page and this example, but I still don't understand how to throw a basic exception using the LLVM's IRBuilder for a non-C++ oriented language.
From my understanding, I have to :
Create a llvm::Value containing the throwed value.
Call "a function", passing it the throwed value. This function will not return.
The example is using a system rewinding function (_Unwind_RaiseException) in order to throw a C++ exception, and I don't really understand how to use my own raising function instead (since I only need to throw an object pointer). What am I missing ?
Short answer is that _Unwind_RaiseException is not a C++-specific function. It comes from the libunwind library, and allows to throw any type of exception.
More details can be found on these blog posts.
As you don't want to use existing C++ exception handling infrastructure, you'll need to replicate parts of it for your language.
You can use the implementation of C unwinder in compiler-rt (or significantly more complex one in libstdc++), and invocation of an unwinder in libstdc++ to start with.
Is there any way to simulate a try-finally or try-except in a language that doesn't have them?
If there's some random, unpredictable, exception happens i need to be sure some cleanup runs.
i could try to be sure that no exception in thrown, that way i am sure my cleanup code always runs - but then i wouldn't need the try-finally/except.
Right this moment i'm trying to create a try-finally in Lua; but i think any solution would work in other languages as well.
Although, for the life of me, i cannot figure out how an exception can be handled without the plumbing provided by the language infrastructure.
But never hurts to ask.
Lua already has the necessary mechanisms to do something not entirely unlike exceptions. Namely pcall.
You can use pcall to execute any Lua function. If that function (or any function it calls) calls error (assert calls error if the assertion condition is not true), then flow control will return to the site of the pcall statement. The pcall will return false and an error message (what is passed to error).
With this, you can "throw" errors and "catch" them. Your "try" is just the pcall; your "catch" statement is what checks the pcall result.
Also, remember: Lua is a garbage collected environment. You shouldn't need to do any cleanup work. Or if you do, you need to change whatever Lua module requires it. Lua APIs should be Lua APIs, not C or C++ APIs.
Never programmed in lua (which is what you have this tagged as). However, several web pages including this one http://jessewarden.com/2011/01/lua-for-actionscript-developers.html mentioned that protected call (pcall) is lua error handling device.
Hope this helps.
How about this Lua Exception Handling system? You can also use Lua RAII mechanisms.
In general, exceptions can be caught using the signal() function. Not sure that lua would support such though. In C, that's what you'd use. And that's a big annoyance! (somewhat complicated.)
Why doesn't F# naturally support a try/with/finally block?
Doesn't it make sense to try something, deal with whatever exception it throws, at least to log the exception, and then be sure that some code executes after all that?
Sure, we can do
try
try
...
with ex -> ...
finally
...
But that seems too artificial, it clearly demonstrates that "F# is against try/with/finally". Why is that?
As somebody already mentioned, you would usually use try-with-finally to make sure that you properly release all resources in case of an exception. I think in most of the cases you can do this more easily using the use keyword:
let input =
try
use stream = new FileStream("C:\temp\test.txt");
use rdr = new StreamReader(stream);
Some(rdr.ReadToEnd())
with :? IOException as e ->
logError(e)
None
I think this is mostly the reason why you don't need try-with-finally as often as you would in other languages. But of course, there are some situations where you may need it (but you could of course avoid that by creating instance of IDisposable using object expressions (which is syntactically very easy). But I think this is so rare that the F# team doesn't really need to worry about this.
Orthogonality? You can simply nest a try-with inside a try-finally, as you show. (This is what happens at the IL level anyway, I think.)
That said, try-with-finally is something that we may consider in a future version of the language.
Personally I have only run into wanting it a couple times, but when you do need it, it is a little bothersome to have to do the extra nesting/indent. In general I find that I rarely write exception handling code, and it's usually just one or the other (e.g. a finally to restore an invariant or other transactional semantics, or a 'catch' near the top of an app to log an exception or show the user diagnostics).
But I don't think there's a lot to 'read in to' regarding the language design here.
Without going into great detail because the great details are in
[Expert .NET 2.0 IL Assembler] 01 by Serge Lidin
See: Ch. 14, Managed Exception Handling
"The finally and fault handlers cannot peacefully coexist with other handlers, so if a guarded block has a finally or fault handler, it cannot have anything else. To combine a finally or fault handler with other handlers, you need to nest the guarded and handler bocks within other guarded blocks, ..., so that each finally or fault handler has its own personal guarded block."
pg. 300
A try/catch uses a fault handler and a try/finally uses a finally handler.
See: ILGenerator.BeginFaultBlock Method
If you emit a fault handler in an exception block that also contains a
catch handler or a finally handler, the resulting code is
unverifiable.
So, all of the .net languages could be consider to be using syntactic sugar and since F# is so new, they just haven't implemented it yet. No harm no foul.
But that seems too artificial, it clearly demonstrates that "F# is against try/with/finally". Why is that?
I guess F# might be "against" exception-handling at all. For the sake of .NET interoperability, it has to support them, but basically, there is no exception-handling* in functional programming.
Throwing/Catching exceptions means performing "jumps to nowhere" that aren't even noticed by the type system which is both fundamentally against the functional philosophy.
You can use purely functional (monadic) code to wrap exceptions. All errors are handled through values, in terms of the underlying type system and free of jumps/side effects.
Instead of writing a function
let readNumber() : int = ...
that may throw arbitrary exceptions, you'll simply state
let readNumber() : int option = ...
which makes this point automatically clear by its type signature.
*This doesn't mean we don't handle exceptional situations, it's just about the kind of exception-handling in .NET/C++.
I will clarify my comment in this answer.
I maintain there is no reason to assume that you want to catch exceptions and finalize some resources at the same level. Perhaps you got used to do it that way in a language in which it was convenient to handle both at the same time, but it's a coincidence when it happens. The finalization is convenient when you do not catch all exceptions from the inner block. try...with is for catching exceptions so that the computation can continue normally. There simply is no relationship between the two (if anything, they go in opposite directions: are you catching the exception, or letting it go through?).
Why do you have to finalize anything at all? Shouldn't the GC be managing unreferenced resources for you? Ah... but the language is trying to give you access to system primitives which work with side-effects, with explicit allocations and de-allocations. You have to de-allocate what you have allocated (in all cases)... Shouldn't you be blaming the rotten interface that the system is providing instead of F#, which is only the messenger in this case?
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 1 year ago.
Improve this question
Google's Go language has no exceptions as a design choice, and Linus of Linux fame has called exceptions crap. Why?
Exceptions make it really easy to write code where an exception being thrown will break invariants and leave objects in an inconsistent state. They essentially force you to remember that most every statement you make can potentially throw, and handle that correctly. Doing so can be tricky and counter-intuitive.
Consider something like this as a simple example:
class Frobber
{
int m_NumberOfFrobs;
FrobManager m_FrobManager;
public:
void Frob()
{
m_NumberOfFrobs++;
m_FrobManager.HandleFrob(new FrobObject());
}
};
Assuming the FrobManager will delete the FrobObject, this looks OK, right? Or maybe not... Imagine then if either FrobManager::HandleFrob() or operator new throws an exception. In this example, the increment of m_NumberOfFrobs does not get rolled back. Thus, anyone using this instance of Frobber is going to have a possibly corrupted object.
This example may seem stupid (ok, I had to stretch myself a bit to construct one :-)), but, the takeaway is that if a programmer isn't constantly thinking of exceptions, and making sure that every permutation of state gets rolled back whenever there are throws, you get into trouble this way.
As an example, you can think of it like you think of mutexes. Inside a critical section, you rely on several statements to make sure that data structures are not corrupted and that other threads can't see your intermediate values. If any one of those statements just randomly doesn't run, you end up in a world of pain. Now take away locks and concurrency, and think about each method like that. Think of each method as a transaction of permutations on object state, if you will. At the start of your method call, the object should be clean state, and at the end there should also be a clean state. In between, variable foo may be inconsistent with bar, but your code will eventually rectify that. What exceptions mean is that any one of your statements can interrupt you at any time. The onus is on you in each individual method to get it right and roll back when that happens, or order your operations so throws don't effect object state. If you get it wrong (and it's easy to make this kind of mistake), then the caller ends up seeing your intermediate values.
Methods like RAII, which C++ programmers love to mention as the ultimate solution to this problem, go a long way to protect against this. But they aren't a silver bullet. It will make sure you release resources on a throw, but doesn't free you from having to think about corruption of object state and callers seeing intermediate values. So, for a lot of people, it's easier to say, by fiat of coding style, no exceptions. If you restrict the kind of code you write, it's harder to introduce these bugs. If you don't, it's fairly easy to make a mistake.
Entire books have been written about exception safe coding in C++. Lots of experts have gotten it wrong. If it's really that complex and has so many nuances, maybe that's a good sign that you need to ignore that feature. :-)
The reason for Go not having exceptions is explained in the Go language design FAQ:
Exceptions are a similar story. A
number of designs for exceptions have
been proposed but each adds
significant complexity to the language
and run-time. By their very nature,
exceptions span functions and perhaps
even goroutines; they have
wide-ranging implications. There is
also concern about the effect they
would have on the libraries. They are,
by definition, exceptional yet
experience with other languages that
support them show they have profound
effect on library and interface
specification. It would be nice to
find a design that allows them to be
truly exceptional without encouraging
common errors to turn into special
control flow that requires every
programmer to compensate.
Like generics, exceptions remain an
open issue.
In other words, they haven't yet figured out how to support exceptions in Go in a way that they think is satisfactory. They are not saying that Exceptions are bad per se;
UPDATE - May 2012
The Go designers have now climbed down off the fence. Their FAQ now says this:
We believe that coupling exceptions to a control structure, as in the try-catch-finally idiom, results in convoluted code. It also tends to encourage programmers to label too many ordinary errors, such as failing to open a file, as exceptional.
Go takes a different approach. For plain error handling, Go's multi-value returns make it easy to report an error without overloading the return value. A canonical error type, coupled with Go's other features, makes error handling pleasant but quite different from that in other languages.
Go also has a couple of built-in functions to signal and recover from truly exceptional conditions. The recovery mechanism is executed only as part of a function's state being torn down after an error, which is sufficient to handle catastrophe but requires no extra control structures and, when used well, can result in clean error-handling code.
See the Defer, Panic, and Recover article for details.
So the short answer is that they can do it differently using multi-value return. (And they do have a form of exception handling anyway.)
... and Linus of Linux fame has called exceptions crap.
If you want to know why Linus thinks exceptions are crap, the best thing is to look for his writings on the topic. The only thing I've tracked down so far is this quote that is embedded in a couple of emails on C++:
"The whole C++ exception handling thing is fundamentally broken. It's especially broken for kernels."
You'll note that he's talking about C++ exceptions in particular, and not exceptions in general. (And C++ exceptions do apparently have some issues that make them tricky to use correctly.)
My conclusion is that Linus hasn't called exceptions (in general) "crap" at all!
Exceptions are not bad per se, but if you know they are going to happen a lot, they can be expensive in terms of performance.
The rule of thumb is that exceptions should flag exceptional conditions, and that you should not use them for control of program flow.
I disagree with "only throw exceptions in an exceptional situation." While generally true, it's misleading. Exceptions are for error conditions (execution failures).
Regardless of the language you use, pick up a copy of Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries (2nd Edition). The chapter on exception throwing is without peer. Some quotes from the first edition (the 2nd's at my work):
DO NOT return error codes.
Error codes can be easily ignored, and often are.
Exceptions are the primary means of reporting errors in frameworks.
A good rule of thumb is that if a method does not do what its name suggests, it should be considered a method-level failure, resulting in an exception.
DO NOT use exceptions for the normal flow of control, if possible.
There are pages of notes on the benefits of exceptions (API consistency, choice of location of error handling code, improved robustness, etc.) There's a section on performance that includes several patterns (Tester-Doer, Try-Parse).
Exceptions and exception handling are not bad. Like any other feature, they can be misused.
From the perspective of golang, I guess not having exception handling keeps the compiling process simple and safe.
From the perspective of Linus, I understand that kernel code is ALL about corner cases. So it makes sense to refuse exceptions.
Exceptions make sense in code were it's okay to drop the current task on the floor, and where common case code has more importance than error handling. But they require code generation from the compiler.
For example, they are fine in most high-level, user-facing code, such as web and desktop application code.
Exceptions in and of themselves are not "bad", it's the way that exceptions are sometimes handled that tends to be bad. There are several guidelines that can be applied when handling exceptions to help alleviate some of these issues. Some of these include (but are surely not limited to):
Do not use exceptions to control program flow - i.e. do not rely on "catch" statements to change the flow of logic. Not only does this tend to hide various details around the logic, it can lead to poor performance.
Do not throw exceptions from within a function when a returned "status" would make more sense - only throw exceptions in an exceptional situation. Creating exceptions is an expensive, performance-intensive operation. For example, if you call a method to open a file and that file does not exist, throw a "FileNotFound" exception. If you call a method that determines whether a customer account exists, return a boolean value, do not return a "CustomerNotFound" exception.
When determining whether or not to handle an exception, do not use a "try...catch" clause unless you can do something useful with the exception. If you are not able to handle the exception, you should just let it bubble up the call stack. Otherwise, exceptions may get "swallowed" by the handler and the details will get lost (unless you rethrow the exception).
Typical arguments are that there's no way to tell what exceptions will come out of a particular piece of code (depending on language) and that they are too much like gotos, making it difficult to mentally trace execution.
http://www.joelonsoftware.com/items/2003/10/13.html
There is definitely no consensus on this issue. I would say that from the point of view of a hard-core C programmer like Linus, exceptions are definitely a bad idea. A typical Java programmer is in a vastly different situation, though.
Exceptions aren't bad. They fit in well with C++'s RAII model, which is the most elegant thing about C++. If you have a bunch of code already that's not exception safe, then they're bad in that context. If you're writing really low level software, like the linux OS, then they're bad. If you like littering your code with a bunch of error return checks, then they not helpful. If you don't have a plan for resource control when an exception is thrown (that C++ destructors provides) then they're bad.
A great use-case for exceptions is thus....
Say you are on a project and every controller (around 20 different major ones) extends a single superclass controller with an action method. Then every controller does a bunch of stuff different from each other calling objects B, C, D in one case and F, G, D in another case. Exceptions come to the rescue here in many cases where there was tons of return code and EVERY controller was handling it differently. I whacked all that code, threw the proper exception from "D", caught it in the superclass controller action method and now all our controllers are consistent. Previously D was returning null for MULTIPLE different error cases that we want to tell the end-user about but couldn't and I didn't want to turn the StreamResponse into a nasty ErrorOrStreamResponse object (mixing a data structure with errors in my opinion is a bad smell and I see lots of code return a "Stream" or other type of entity with error info embedded in it(it should really be the function returns the success structure OR the error structure which I can do with exceptions vs. return codes)....though the C# way of multiple responses is something I might consider sometimes though in many cases, the exception can skip a whole lot of layers(layers that I don't need to clean up resources on either).
yes, we have to worry about each level and any resource cleanup/leaks but in general none of our controllers had any resources to clean up after.
thank god we had exceptions or I would have been in for a huge refactor and wasted too much time on something that should be a simple programming problem.
Theoretically they are really bad. In perfect mathematical world you cannot get exception situations. Look at the functional languages, they have no side effects, so they virtually do not have source for unexceptional situations.
But, reality is another story. We always have situations that are "unexpected". This is why we need exceptions.
I think we can think of exceptions as of syntax sugar for ExceptionSituationObserver. You just get notifications of exceptions. Nothing more.
With Go, I think they will introduce something that will deal with "unexpected" situations. I can guess that they will try to make it sound less destructive as exceptions and more as application logic. But this is just my guess.
The exception-handling paradigm of C++, which forms a partial basis for that of Java, and in turn .net, introduces some good concepts, but also has some severe limitations. One of the key design intentions of exception handling is to allow methods to ensure that they will either satisfy their post-conditions or throw an exception, and also ensure that any cleanup which needs to happen before a method can exit, will happen. Unfortunately, the exception-handling paradigms of C++, Java, and .net all fail to provide any good means of handling the situation where unexpected factors prevent the expected cleanup from being performed. This in turn means that one must either risk having everything come to a screeching halt if something unexpected happens (the C++ approach to handling an exception occurs during stack unwinding), accept the possibility that a condition which cannot be resolved due to a problem that occurred during stack-unwinding cleanup will be mistaken for one which can be resolved (and could have been, had the cleanup succeeded), or accept the possibility that an unresolvable problem whose stack-unwinding cleanup triggers an exception that would typically be resolvable, might go unnoticed as code which handles the latter problem declares it "resolved".
Even if exception handling would generally be good, it's not unreasonable to regard as unacceptable an exception-handling paradigm that fails to provide a good means for handling problems that occur when cleaning up after other problems. That isn't to say that a framework couldn't be designed with an exception-handling paradigm that could ensure sensible behavior even in multiple-failure scenarios, but none of the top languages or frameworks can as yet do so.
I havent read all of the other answers, so this ma yhave already been mentioned, but one criticism is that they cause programs to break in long chains, making it difficult to track down errors when debugging the code. For example, if Foo() calls Bar() which calls Wah() which calls ToString() then accidentily pushing the wrong data into ToString() ends up looking like an error in Foo(), an almost completely unrelated function.
For me the issue is very simple. Many programmers use exception handler inappropriately. More language resource is better. Be capable to handle exceptions is good. One example of bad use is a value that must be integer not be verified, or another input that may divide and not be checked for division of zero... exception handling may be an easy way to avoid more work and hard thinking, the programmer may want to do a dirty shortcut and apply an exception handling... The statement: "a professional code NEVER fails" might be illusory, if some of the issues processed by the algorithm are uncertain by its own nature. Perhaps in the unknown situations by nature is good come into play the exception handler. Good programming practices are a matter of debate.
Exception not being handled is generally bad.
Exception handled badly is bad (of course).
The 'goodness/badness' of exception handling depends on the context/scope and the appropriateness, and not for the sake of doing it.
Okay, boring answer here. I guess it depends on the language really. Where an exception can leave allocated resources behind, they should be avoided. In scripting languages they just desert or overjump parts of the application flow. That's dislikable in itself, yet escaping near-fatal errors with exceptions is an acceptable idea.
For error-signaling I generally prefer error signals. All depends on the API, use case and severity, or if logging suffices. Also I'm trying to redefine the behaviour and throw Phonebooks() instead. The idea being that "Exceptions" are often dead ends, but a "Phonebook" contains helpful information on error recovery or alternative execution routes. (Not found a good use case yet, but keep trying.)
Most program languages have some kind of exception handling; some languages have return codes, others have try/catch, or rescue/retry, etc., each with its own pecularities in readability, robustness, and practical effectiveness in a large group development effort. Which one is the best and why ?
I would say that depends on the nature of your problem. Different problem domains could require almost arbitrary error messages, while other trivial tasks just can return NULL or -1 on error.
The problem with error return codes is that you're polluting/masking the error since it can be ignored (sometimes without the API client not knowing they should check for the error code). It gives a (reasonably) valid output from the method at hand.
Imagine you have an API where you ask for a index key for some map, store it in a list, and then continue running. The API then at a later moment sends a callback, and that method might then traverse the table, using the key which might be -1 in this example (the error code). BOOM, the application crashes as you index to -1 in some array, and those kinds of problems can be very hard to nail down. This is still a trivial example, but it illustrates a problem with error codes.
On the other hand, error codes are faster than throwing exceptions, and you might want to use them for frequently accessed method calls - if it is appropriate to return such an error code. I would say that trying to encapsulate these kinds of error codes within a private assembly would be quite OK since you're not exposing those error codes to the client of the API. Always remember to document these methods rigorously since these kinds of application nukes can linger around in an application for a long time since they were triggered before it goes off.
Personally, I prefer a mix of them both to some extent. I use exceptions just for that - exceptions - when the program runs into a state which was not expected and needs to inform something has gone way out of plan. I am not a sucker of writing try/catch blocks all over my code, but it's all down to personal preference.
Best for what? Language design is always about tradeoffs. The advantage of return codes is that they don't require any runtime support beyond regular function calls; the disadvantages are 1) you always have to check them 2) the return type has to have a failure value that isn't a valid result of the function call.
The advantage of automatic exception handling is that error conditions in your code don't disappear.
The differences between exception handling semantics in various languages (and Lisp's condition system, E's ejectors, etc) mainly show up in how stack unwinding is dealt with when program execution should continue.
To summarize, though: automatic exception handling is extremely valuable when you need to write readable, robust software, especially in a large team. Letting the computer track error conditions for you gives you one less thing to think about when reading code, and it removes an opportunity for error. The only time I'd use return codes to indicate errors is if I was implementing a language with exception handling in one that didn't have it.
try/catch/finally does the job admirably.
It allows the programmer to handle specific conditions as well as general failures gracefully.
All said and done I'm sure that each is as good as any other.
I'd have to go with the try / catch concept. I feel like in terms of readability this provides the most to a code maintainer. It should be fairly straight forward to find the chain of function calls as long as the exception is properly typed and the associated message contains detailed enough data (I personally do not like including stack traces but I know plenty who do and this would make this even more traceable.) The return code implementation requires an external table of code definitions on a program by program basis. Which from personal experience is both unwieldy to maintain and reference.
For unusual perspective on exception handling, see Haskell's Control.Exception monad