When executing a program, there is always the possibility of an unexpected runtime error occurring. These occur when a program tries to perform an illegal operation. This kind of scenario can be triggered by events such as division by 0 or a pointer which tries to reference an invalid memory address. We can significantly improve … Continue reading "IEC 61131-3: Exception Handling with __TRY/__CATCH"
When executing a program, there is always the possibility of an unexpected runtime error occurring. These occur when a program tries to perform an illegal operation. This kind of scenario can be triggered by events such as division by 0 or a pointer which tries to reference an invalid memory address. We can significantly improve the way these exceptions are handled by using the keywords __TRY and __CATCH.
The list of possible causes for runtime errors is endless. What all these errors have in common is that they cause the program to crash. Ideally, there should at least be an error message with details of the runtime error:
Because this leaves the program in an undefined state, runtime errors cause the system to halt. This is indicated by the yellow TwinCAT icon:
For an operational system, an uncontrolled stop is not always the optimal response. In addition, the error message does not provide enough information about where in the program the error occurred. This makes improving the software a tricky task.
To help track down errors more quickly, you can add check functions to your program.
Check functions are called whenever the relevant operation is executed. The best known is probably CheckBounds(). Each time an array element is accessed, this function is implicitly called beforehand. The parameters passed to this function are the array bounds and the index of the element being accessed. This function can be configured to automatically correct attempts to access elements which are out of bounds. This approach does, however, have some disadvantages.
CheckBounds() is not able to determine which array is being accessed, so error correction has to be the same for all arrays.
Because CheckBounds() is called whenever an array element is accessed, it can significantly slow down program execution.
It’s a similar story with other check functions.
It is not unusual for check functions to be used during development only. Check functions include breakpoints, which stop the program when an operation throws up an error. The call stack can then be used to determine where in the program the error has occurred.
The ‘try/catch’ statement
Runtime errors in general are also known as exceptions. IEC 61131-3 includes __TRY, __CATCH and __ENDTRY statements for detecting and handling these exceptions:
The TRY block (the statements between __TRY and __CATCH) contains the code with the potential to throw up an exception. Assuming that no exception occurs, all of the statements in the TRY block will be executed as normal. The program will then continue from the line immediately following the __ENDTRY statement. If, however, one of the statements within the TRY block causes an exception, the program will jump straight to the CATCH block (the statements between __CATCH and __ENDTRY). All subsequent statements within the TRY block will be skipped.
The CATCH block is only executed if an exception occurs; it contains the error handling code. After processing the CATCH block, the program continues from the statement immediately following __ENDTRY.
The __CATCH statement takes the form of the keyword __CATCH followed, in brackets, by a variable of type __SYSTEM.ExceptionCode. The __SYSTEM.ExceptionCode data type contains a list of all possible exceptions. If an exception occurs, causing the CATCH block to be called, this variable can be used to query the cause of the exception.
The following example divides two elements of an array by each other. The array is passed to the function using a pointer. If the return value is negative, an error has occurred. The negative return value provides additional information on the cause of the exception:
FUNCTION F_Calc : LREAL
VAR_INPUT
pData : POINTER TO ARRAY [0..9] OF LREAL;
nElementA : INT;
nElementB : INT;
END_VAR
VAR
exc : __SYSTEM.ExceptionCode;
END_VAR
__TRY
F_Calc := pData^[nElementA] / pData^[nElementB];
__CATCH (exc)
IF (exc = __SYSTEM.ExceptionCode.RTSEXCPT_ARRAYBOUNDS) THEN
F_Calc := -1;
ELSIF ((exc = __SYSTEM.ExceptionCode.RTSEXCPT_FPU_DIVIDEBYZERO) OR
(exc = __SYSTEM.ExceptionCode.RTSEXCPT_DIVIDEBYZERO)) THEN
F_Calc := -2;
ELSIF (exc = __SYSTEM.ExceptionCode.RTSEXCPT_ACCESS_VIOLATION) THEN
F_Calc := -3;
ELSE
F_Calc := -4;
END_IF
__ENDTRY
The ‘finally’ statement
The optional __FINALLY statement can be used to define a block of code that will always be called whether or not an exception has occurred. There’s only one condition: the program must step into the TRY block.
We’re going to extend our example so that a value of one is added to the result of the calculation. We’re going to do this whether or not an error has occurred.
FUNCTION F_Calc : LREAL
VAR_INPUT
pData : POINTER TO ARRAY [0..9] OF LREAL;
nElementA : INT;
nElementB : INT;
END_VAR
VAR
exc : __SYSTEM.ExceptionCode;
END_VAR
__TRY
F_Calc := pData^[nElementA] / pData^[nElementB];
__CATCH (exc)
IF (exc = __SYSTEM.ExceptionCode.RTSEXCPT_ARRAYBOUNDS) THEN
F_Calc := -1;
ELSIF ((exc = __SYSTEM.ExceptionCode.RTSEXCPT_FPU_DIVIDEBYZERO) OR
(exc = __SYSTEM.ExceptionCode.RTSEXCPT_DIVIDEBYZERO)) THEN
F_Calc := -2;
ELSIF (exc = __SYSTEM.ExceptionCode.RTSEXCPT_ACCESS_VIOLATION) THEN
F_Calc := -3;
ELSE
F_Calc := -4;
END_IF
__FINALLY
F_Calc := F_Calc + 1;
__ENDTRY
The statement in the FINALLY block (line 24) will always be executed whether or not an exception has occurred.
If no exception occurs within the TRY block, the FINALLY block will be called straight after the TRY block.
If an exception does occur, the CATCH block will be executed first, followed by the FINALLY block. Only then will the program exit the function.
__FINALLY therefore enables you to perform various operations irrespective of whether or not an exception has occurred. This generally involves releasing resources, for example closing a file or dropping a network connection.
Extra care should be taken in implementing the CATCH and FINALLY blocks. If an exception occurs within these blocks, it will give rise to an unexpected runtime error, resulting in an immediate uncontrolled program stop.
The sample program runs under 32-bit TwinCAT 3.1.4024 or higher. 64-bit systems are not currently supported.
Are you looking for investment in Pakistan? Then Bahria Enclave Plots For Sale is going on and this is the very best and affordable investment nowadays in Pakistan with high profit rate.
Choosing the best router table is the very first thing before starting any wood works because this is the only way to make any wood works perfect.
Muscle spasm is the very critical problem nowadays, there are lots of oils but it's hard to identify which one is good for muscle spasm. We've research and identify Top 5 Essential Oils For Muscle Spasm for beneficial.
Wenn Du deinen Benutzernamen in Besitz nehmen möchtest, solltest Du dich registrieren:
Benutzername
Passwort
Passwort wiederholen
E-Mail
Stefan Henneken
Größtenteils wird es hier um .NET und C# gehen. In Gegensatz zu vielen anderen Blogs, werde ich versuchen die einzelnen Themen intensiv zu behandeln. Aus diesem Grund bestehen die meisten Beiträge aus mehreren Teilen. Die einzelnen Teile bauen aufeinander auf, können aber auch einzeln betrachtet werden.