GOTO from Try/catch block in VB.NET - vb.net

Yes, I know that GOTO is wrong and every time I use it a kitten dies ;) Still one thing makes me curious:
What if I use GOTO in try/catch block
Try
...some code...
Catch
...some code...
GoTo Label1
End Try
...some more code to be skipped if error
Label1:
...rest of code...
Do I understand correctly that the try/catch block will never get closed in the program and it may cause problems? Or not?
There seems to be also some OnError GoTo command but I don't have much experience with it. Maybe my code could be rewriten using it?

Do I understand correctly that the try/catch block will never get closed
No, the try/catch block will be closed because you leave it. It is okay to jump out of the try/catch block.
However, the code should be rewritten to:
Try
...some code...
...some more code to be skipped if error
Catch
...some code...
End Try
...rest of code...

It may be instructive to learn a little about the .NET framework internals:
Exception handling is supported in the CLI through exception objects and protected blocks of code.
(CLI = Common Language Infrastructure)
In the CLI, a method can define a range of CIL instructions that are said to be protected. This is called a try block. It can then associate one or more handlers with that try block. If an exception occurs during execution anywhere within the try block, an exception object is created that describes the problem. The CLI then takes over, transferring control from the point at which the exception was thrown, to the block of code that is willing
to handle that exception.
And this is all done in a declarative manner. So, basically, the Try, Catch, End Try etc items aren't emitted as instructions - the compiler says "if an exception happens in this range of instructions, here are the possible handlers to jump to". And it only consults this information when an exception occurs. So your concern:
the try/catch block will never get closed
isn't valid because the one mechanism for leaving a protected region is... (drum roll please)... to move outside of that range of instructions. It doesn't matter how this is done - it could just be by running out of the end of the protected range, or via a GOTO, or via an exception.
First two quotes are from MS Partition I (section 12.4.2) and MS Partition II (section 19) documents available for download from ECMA C# and Common Language Infrastructure Standards
Section 12.4.2 of Partition I also states:
Protected regions, the type of the associated handler, and the location of the associated handler and (if needed)
user-supplied filter code are described through an Exception Handler Table associated with each method

Related

When Others Then VS. When exception Then

Whats the benefit of doing:
EXCEPTION
WHEN [error code] THEN
[Handle Exception]
WHEN [error code1] THEN
[Handle Exception1]
END;
Over this:
EXCEPTION
WHEN Others THEN
IF sqlcode=[error code] THEN
[Handle Exception]
ELSIF sqlcode=[error code1] THEN
[Handle Exception1]
END IF;
END;
I have heard it is bad practice to use others the way I am demonstrating in my second example but I'm not really sure why. They are both handling the exceptions so whats the issue?
Also I've heard that I should be putting raises in my when others statements otherwise errors could be hidden from outer code blocks. Is this true?
I am very new to pl/sql so if any can expand on these point it would be very helpful.
Source code is read more often than it is written. If your code is expressive and conforms to standard it is easier for other people to understand (and "other people" includes you in six months time).
The standard approach to the exception block is to have separate WHEN clauses for specific exceptions we need to handle, and use WHEN OTHERS should we need a default handler for all other exceptions. Having code for specific exceptions under a WHEN OTHERS clause is non-conforming and unnecessary.
"I've heard that I should be putting raises in my when others statements otherwise errors could be hid from outer code blocks? "
Generally speaking, yes. Following on from my previous point, we should write explicit handling for specific forseeable exceptions. The WHEN OTHERS clause is reserved for everything else, that is unforeseen exceptions, so it is highly unlikely that we can write a generic handler which is appropriate for all situations. It is important to re-raise the exception and allow the calling program to decide how to handle it.
In fact the same observation will often apply to defined exceptions too. It is okay to handle and suppress some exceptions (e.g. sometimes we can handle NO_DATA_FOUND with default values) but usually the calling program needs to know that an exception occurred and the called program didn't follow the expected path.
As far as handling an exception goes, the important thing is to log as much information as possible, including the real error message and pertinent variables or parameters. No EMPLOYEE records for DEPTNO = [40] is more useful than Error happened. Also dbms_output.put_line is not logging: in real life we need information persisted to a table or a file, because PL/SQL programs are usually run in the background, not a client, so there's no screen to output to.

Can .NET SqlConnection.Dispose() throw an exception?

Is it possible for the Dispose method of a SqlConnnection object to throw an exception? It's always shown sitting on its own in a finally block outside of the try-catch. And if a using block is equivalent to a try...finally which then calls Dispose, that would also seem to be a case when an exception thrown by Dispose would be problematic.
Technically it can, but it shouldn't:
CA1065: Do not raise exceptions in unexpected locations :
A IDisposable.Dispose method should not throw an exception. Dispose is often called as part of the clean up logic in a finally clause. Therefore, explicitly throwing an exception from Dispose forces the user to add exception handling inside the finally clause.
The Dispose(false) code path should never throw exceptions, because this is almost always called from a finalizer.
Dispose Dos and Don'ts:
Don't throw exceptions in Dispose. Nothing should go wrong with your object calling Dispose.
The moral of the story appears to be that an exception thrown from Dispose is a very bad thing (for some of the reasons you mentioned) and should be handled as high as possible (there's nothing you can do about it, and probably can't recover from it).
In general, a block of code should finish normally if the state of the system will match what the surrounding code expects, and throw an exception if it won't. The the try/catch/finally construct in .NET has a weakness, however, which flows into the IDisposable interface which is designed to work with it (via language constructs like using): a method
void Test()
{
try
{
doSomething();
}
finally
{
doCleanup();
}
}
should only exit normally if both doSomething() and doCleanup() succeed, but if doSomething() throws an exception, the Test() method as a whole should either throw that exception or make it possible to log it. Meeting both requirements would require either that doCleanup() throw an exception of it runs following a successful call to doSomething(), but not following a call which threw an exception, or else that any exception it throws incorporates information about the exception thrown from doSomething().
Unfortunately, there is no convenient way of writing a finally block to vary its behavior based upon the result of the try , nor is there any way for a Dispose() method invoked from a finally to do so. Thus, it is necessary for Dispose implementations to try to guess whether it's more evil to exit normally when an operation fails, or throw an exception which may overwrite an earlier one that held useful information. The latter is somewhat evil, but often not as evil as the former.
For example, consider the pseudocode:
RenameFile(mainFileName, backupFileName);
using(outFile = File.Create(mainFileName);
{
writeDataToNewFile(outFile);
}
DeleteFile(backupFileName);
If something goes wrong while closing the output file and the exception gets propagated out of the using block, the backup file will be left intact and might be recovered later. If the using block were allowed to complete normally despite a failure which prevented the main file from being properly written, the backup file would get deleted, possibly destroying the only copy of some of the data contained therein.
The idea that Dispose shouldn't throw exceptions relates to the fact that there's often no good way to handle exceptions thrown from Dispose. The bigger problem, however, is that there's no good way of handling problems that arise during Dispose without knowing the circumstances under which it is invoked. Throwing an exception from Dispose may be somewhat evil, but still be less evil than allowing it to complete normally in cases where real problems exist.

Best Way to Handle Errors with AppleScript-ObjC embedded in Cocoa App?

I'm invoking a small AppleScript handler from within a larger Cocoa/Objective-C app (using the AppleScript-ObjC framework to call the AppleScript methods directly from the Objective-C code). I originally tried using Scripting Bridge, but that didn't work for me due to compatibility problems with the external app. The only purpose of the AppleScript is essentially to send a small string to the external app. This is the first time I've attempted to do something like this in order to control an external application, so please bear with me if I'm making an obvious mistake.
Occasionally, the AppleScript may encounter errors depending on the state of the external application, and I would like to handle those errors appropriately in my Objective-C code.
The way I'm doing this right now is that I have a try block in the AppleScript:
try
-- Do stuff
return the number 0
on error the error_message number the error_number
return the error_number
end try
I return zero if the script finishes normally, and return the error number if it doesn't. Then in the Objective-C code, I test the return value and throw a "normal" exception in cases where there is an error, so that I can handle that in my regular exception-handling code.
This works, but is there a way to trap the AppleScript exception directly from the Objective-C code? When I run the code without the AppleScript try-error code in XCode, it seems that it hits my exception breakpoint before it returns from the AppleScript, but it never invokes the #catch block for NSException. Is there some way to catch that exception that is being hit somehow? I'm guessing the answer is no, but I wanted to check that there isn't some better way to do this than what I'm doing. Apple's documentation on AppleScript-ObjC is rather sparse, and mostly just discusses handling errors within AppleScript.
Update:
So, I just tried playing around with the breakpoint setup a little bit, and it turns out that it's a C++ exception being sent from the AppleScript code, not an Objective-C one. That's why it wasn't being caught by the #catch block I was using. It seems that the AppleScript-ObjC mechanism uses exceptions for control flow/recoverable errors, and I had my breakpoint set up to break when they are thrown. So, I think it's probably best to just catch the errors in the AppleScript application, and return an error code as a string or integer to the Objective-C code.
AppleScript uses C++ exceptions to implement its own exceptions, but nothing else; you shouldn’t see them in code that completes successfully. If an AppleScript exception escapes to point of returning to Objective-C, the bridge actually swallows it -- you should get a log message, and a nil/zero/NO return value from the bridged method. The upshot of all this is that you’re already doing the right thing: trap the error in AppleScript and return something that your Objective-C code can detect.
As a side note, AppleScriptObjC is mainly intended for developers writing applications primarily or entirely in AppleScript. If you’re writing a primarily Objective-C application with a few bits that control other applications via scripting, consider using ScriptingBridge instead.

Why does NSOperation example code uses #try & #catch

In Apple's Concurrency Programming Guide the NSOperation subclass examples (both non-concurrent and concurrent varieties) use exception handling and I'm wondering why they are encouraging this style within operations.
Listing 2-4 Responding to a cancellation request
- (void)main {
#try {
BOOL isDone = NO;
while (![self isCancelled] && !isDone) {
// Do some work and set isDone to YES when finished
}
}
#catch(...) {
// Do not rethrow exceptions.
}
}
My understanding is that generally exception handling is not a common practice in Objective-C code - exceptions are essentially programmer errors and should cause the app to crash whereas unexpected inputs are best handled by NSError. (My possibly misinformed understanding comes from things like this and this)
I'm wondering if NSOperations present a particular situation in which exception handling is important, or if this is more the preferred style of the particular author of that guide.
As a side note, some of the NSOperation example code follows this style, other examples do not. Most high-visibility OSS does not use exceptions (AFNetworking, for example).
Your understanding is correct - NSError (or similar) should be used to convey error information, rather than exceptions. Most Objective-C code is not exception-safe and will at the very least leak resources. As a general rule, never let your code leak an exception into anyone else's code - whether Apple's or a 3rd parties. Some 3rd party frameworks may explicitly indicate they are exception safe, but it's rare.
By that principle you can see why you should have a catch-all exception handler in your main method regardless. But there's actually another reason: your operation will be run on a dedicated thread. Exceptions thrown from your operation will propagate up the stack, but no further. The logical caller or owner of the operation won't get them, as they're running on a different thread (or not at all). So leaked exceptions will either kill your whole program, or be swallowed silently with no other indication. Your program may then get stuck in a weird state - since you didn't realise an error occurred, you may continue waiting for the result of your operation that will never arrive.
Additionally, Apple has a section in the Concurrency Programming Guide where they talk about Handling Errors and Exceptions. Their first point on "discrete entities" is alluding to what I said in the previous paragraph:
Handling Errors and Exceptions
Because operations are essentially
discrete entities inside your application, they are responsible for
handling any errors or exceptions that arise. In OS X v10.6 and later,
the default start method provided by the NSOperation class does not
catch exceptions. (In OS X v10.5, the start method does catch and
suppress exceptions.) Your own code should always catch and suppress
exceptions directly. It should also check error codes and notify the
appropriate parts of your application as needed. And if you replace
the start method, you must similarly catch any exceptions in your
custom implementation to prevent them from leaving the scope of the
underlying thread.
Among the types of error situations you should be prepared to handle
are the following:
Check and handle UNIX errno-style error codes.
Check explicit error
codes returned by methods and functions.
Catch exceptions thrown by
your own code or by other system frameworks.
Catch exceptions thrown
by the NSOperation class itself, which throws exceptions in the
following situations:
When the operation is not ready to execute but
its start method is called
When the operation is executing or finished
(possibly because it was canceled) and its start method is called
again
When you try to add a completion block to an operation that is
already executing or finished
When you try to retrieve the result of
an NSInvocationOperation object that was canceled
If your custom code
does encounter an exception or error, you should take whatever steps
are needed to propagate that error to the rest of your application.
The NSOperation class does not provide explicit methods for passing
along error result codes or exceptions to other parts of your
application. Therefore, if such information is important to your
application, you must provide the necessary code.
I think this post and the accompanying answer elaborates very well on the general exception- vs. no exception handling topic!
It is unsafe to throw exceptions in circumstances where resources are
not automatically managed. This is the case of the Cocoa framework
(and neighbor frameworks), as they use manual reference counting.
If you throw an exception, any release call you skip over by unwinding
the stack will result in a leak. This should limit you tothrowing only
if you're certain that you're not going to recover since all resources
are returned to the OS when a process quits.
Unfortunately, NSRunLoops tend to catch all exceptions that propagate
to them, so if you throw during an event, you'll resume to the next
event. This is, obviously, very bad. Therefore, it's better that you
simply don't throw.
This problem is diminished if you use garbage-collected Objective-C,
as any resource represented by an Objective-C object will be properly
released. However, C resources (such as file descriptors or
malloc-allocated memory) that are not wrapped in an Objective-C object
will still leak.
So, all in all, don't throw.
The Cocoa API has several workarounds to this, as you mentioned.
Returning nil and the NSError** pattern are two of them.

What’s the rationale behind the Cocoa exception policy - or why use exceptions only for programmer errors?

What’s the rationale behind the Cocoa exception policy - or why use exceptions only for programmer errors?
I understand that exception used to be rather expensive so one would not want to overuse them. But that changed with the modern runtime and it’s zero-cost exceptions. I also understand that the use of exceptions to do general control flow is not a good idea because it could lead to code that is rather hard to understand.
But why should one use exceptions to signal programmer errors? For that case logging a message followed by abort() should be enough. Why should I write a #catch(...) block to handle a programmer error instead of fixing the actual mistake? I’ve been thinking about this a lot and I haven’t found any reasonable use of an exception for a programmer error.
(As a side note/question: I’ve written a recursive descent parser, and I’m planning on using exceptions in there for handling errors. Seems to be much more reasonable to me than adding an out parameter to every single function in there and manually check for an error everywhere. Of course I’ll catch any exceptions I throw in the top level methods that get called from the outside. Anyone think that’s a bad use for exceptions?)
Update: The real question
Thanks for all the answers so far. They all are true, but they don’t actually answer my question. So I guess I wasn’t really clear about it, sorry for that. So here’s the real question:
Why does Cocoa throw exceptions for programmer errors (or assertions) at all? One isn’t supposed to catch them, and actually writing code that handles a programmer error somewhere down the call stack is not a good idea anyways. Seems to me that exceptions there are a wasted effort. Simply logging the error and calling abort() (which exits the program) should be enough. So what’s the advantage there of actually having an exception thrown?
I understand why exceptions are not generally used and discouraged - most parts of Cocoa are just not exception safe. And that’s not the question here. I hope I made this clear now.
Why should I write a #catch(...) block to handle a programmer error instead of fixing the actual mistake?
In most cases, you wouldn't. In Objective-C, you generally don't handle exceptions. If an exception occurs, it causes a crash, and then you fix the bug -- hopefully you catch this during testing.
Of course, in some cases this doesn't work out. Maybe you do except an exception and you can workaround it, so you catch it. Or there's there rare API that'll throw exceptions instead of using error objects.
To be honest, I very, very rarely use try/catch in my Objective-C code.
As for the rationale, I think it's largely due to Objective-C's C heritage. Back in the early 80s when Objective-C was developed, exceptions were kind of "new" (i.e., not in many mainstream languages yet), and Objective-C catered more to the C tradition of using NULL or an out parameter to signal errors.
Your question explicitly assumes that "one isn’t supposed to catch them." This is incorrect. The programmer isn't expected to catch them under normal circumstances, but that isn't to say that they must never be caught for any purpose.
Example: I'm not sure if it does anymore since it's much less buggy these days, but I know it at least used to be the case that Xcode would catch exceptions and put up a dialog saying, "Such-and-such happened. It doesn't appear to be a critical problem, but you should probably save and restart the program to avoid any trouble in the future."
Why does Cocoa throw exceptions for
programmer errors (or assertions) at
all? One isn’t supposed to catch them,
and actually writing code that handles
a programmer error somewhere down the
call stack is not a good idea anyways
Ah!
Three reasons leap to mind.
One, if you catch an exception more or less at your main run loop you could autosave state to a temporary location, crash, and on restart have a "try to restore from just before the crash, warning: may cause another crash and you should check your data very carefully" dialog/sheet/thingie. Or even just catch the exception and tell the user to do a "Save As", quit and restart.
Two, things like the unit test framework make good use of exceptions to abort the current test (logging a failure), and continuing with the rest of the tests. This lets you see if a change you made has one regression (that happens to index a NSArray out of bounds), or if you have six regressions (one or more of which throw an exception).
Three, maybe when added to ObjC it was intended to handle many kinds of errors with exceptions, and after real world experience the useful scope was determined to be "nearly fatal errors only".
The main reason for avoiding throwing exceptions is that you may accidentally throw them through stack frames that are not exception aware. For instance, if a data source for a table view throws an exception, that is not caught and handled before the delegate method returns control to the table view, it might cause all sorts of trouble as it unwinds the table view's stack frames, side stepping various releases of temporary objects and other resources.
Having said that, I personally like exceptions and use them wherever I think they are the natural thing to do, but with the caveat of never allowing them to propagate to code that is not documented as exception aware.
There are likely a lot of reasons. The "historical reasons" others have covered is sufficient to explain the current state of affairs, but there are other possibilities.
Another possibility is Objective C is not typically a "Resource Acquisition Is Initialization" kind of language (yes this is more a library issue then a language issue, but it is real). So most Objective C code that has an error thrown through it will leave invalid program state (things still locked, over retained objects). All things you could deal with if you were thinking about it, and not all things RAII would magically fix (there is a lot of exception unsafe C++ code out there, and C++ is largely RAII).
As noted above stating that you do handle an exception is free(ish), but actually having one thrown is costly (maybe an order of magnitude or two more costly then an extra parameter and a conditional check). So if your parser (for example) uses them to signal errors in parsing, being given a document with a lot of errors can take a LOT longer to parse then if you had explicit checks for an error parameter.
Personally I like exceptions, and would prefer to throw exceptions from my libraries when things "go wrong", but that isn't the Cocoa way, so I use exceptions to handle programmer errors and an error indication and NSError** for other things. It isn't great, but it makes it so other people can use my libraries without having to learn a new way to write Objective C code.
The modern runtime does not give you zero-cost exceptions, it gives you exceptions that only incur their cost if an exception is thrown.