tfm-report/Secciones/background.tex

422 lines
31 KiB
TeX

% !TEX encoding = UTF-8
% !TEX spellcheck = en_GB
% !TEX root = ../paper.tex
\chapter{Background}
\label{cha:background}
Before delving into the specific problems that exist in program slicing currently, let's explore the surface of this thesis' relevant fields: program slicing and exception handling. The last one will be focused specifically on the Java programming language, but could be generalized to other popular programming languages which feature a similar exception handling system (e.g., Python, JavaScript, C++).
\section{Program slicing}
This section provides a series of definitions and background information so that future definitions can be grounded in a common foundation.
\begin{definition}[Slicing criterion] \label{def:slicing-criterion}
Given a program $P$, composed of statements and containing variables $x_1, x_2 ... x_n \in \textnormal{vars}$, a \textit{slicing criterion} is a tuple $\langle s, v \rangle$ where $s \in P$ is a single statement that belongs to the program, and $v$ is a set of variables from $P$.
\end{definition}
The reader should note that the variables in $v$ may not appear in $s$.
\begin{definition}[Execution history] \label{def:execution-history}
Given a program $P$, composed of a set of statements $S = \{s_1, s_2, s_3 ... s_n\}$, and a set of input values $I$, the \textit{execution history} of $P$ given $I$ is the list of statements $H$ that is executed, in the order that they were executed.
\end{definition}
\textit{Program slicing} is the process of extracting a slice given a program and a slicing criterion. A \textit{slice} is a subset of statements of a program which behaves like the original program, at the slicing criterion.
Until now, the concept of slicing has been centred around finding the instructions that affect a variable.
That is the original definition, but as time has progressed, variations have been proposed.
The variation described until now is called \textit{static backward slicing}.
It is also the one that will be used throughout this thesis, though the errors detected and solutions proposed can be easily generalized to others.
The different variations are described later in this chapter, but there exist two fundamental dimensions along which the slicing problem can be proposed \cite{Sil12}:
\begin{itemize}
\item \textit{Static} or \textit{dynamic}: slicing can be performed statically or dynamically.
\textit{Static slicing} \cite{Sil12} produces slices that consider all possible executions of the program: the slice will be correct regardless of the input supplied.
In contrast, \textit{dynamic slicing} \cite{KorL88,AgrH90b} considers a single execution of the program, thus, limiting the slice to the statements present in an execution log.
The slicing criterion is expanded to include a position in the execution history that corresponds to one instance of the selected statement, making it much more specific.
It may help find bugs related to indeterministic behaviour---such as a random or pseudo-random number generator---but, despite selecting the same slicing criterion in the same program, the slice must be recomputed for each set of input values or execution considered.
\item \textit{Backward} or \textit{forward}: \textit{backward slicing} \cite{Sil12} looks for the statements that affect the slicing criterion.
It sits among the most commonly used slicing technique.
In contrast, \textit{forward slicing} \cite{BerC85,GalL91} computes the statements that are affected by the slicing criterion.
There also exists a middle-ground approach called \textit{chopping} \cite{JacR94}, which is used to find all the statements that affect some variables in the slicing criterion and at the same time they are affected by some other variables in the slicing criterion.
\end{itemize}
Since the seminal definition of program slicing by Weiser \cite{Wei81}, the most studied variation of slicing has been \textit{static backward slicing}, which has been informally defined at the beginning of this section and on Section~\ref{sec:motivation}.
That definition can be split in two sub-types, \textit{strong} and \textit{weak} slices, with different levels of requirements and uses in different fields. First, though, we need to introduce and additional concept: the sequence of values.
\begin{definition}[Sequence of values \cite{PerST19}]
\label{def:seq}
Let $P$ be a program and $\langle s, v\rangle$ be a slicing criterion of $P$. $seq(P, s, v)$ is the sequence of values the slicing criterion $v$ is evaluated to, at $s$, during the execution of $P$.
\end{definition}
\begin{definition}[Strong static backward slice \cite{Wei81,GalL91}]
\label{def:strong-slice}
Given a program $P$ and a slicing criterion $SC = \langle s,v \rangle$, $S$ is a \textit{strong static backward slice} of $P$ with
respect to $SC$ if $S$ fulfils the following properties:
\begin{enumerate}
\item $S$ is an executable program.
\item $S \subseteq P$, or $S$ is the result of removing 0 or more statements from $P$.
\item For any possible input, $\mathit{seq}(P, s, v) = \mathit{seq}(S, s, v)$.
\end{enumerate}
\end{definition}
% \sergio{Esta definicion no obligaba tambien a acabar con el mismo error en caso de que la ejecucion no termine? Si es asi, plantearse poner algo al respecto.}
% \josep{hay que revisar la definición de (1) Weiser, (2) Binkley y Gallagher y (3) Frank Tip. Mi opinion es que NO: Creo que no es necesario que el error se repita. Lo que dice es que el valor de las variables del SC debe ser el mismo, pero no dice nada del error.}
\begin{definition}[Weak static backward slice \cite{BinG96}]
\label{def:weak-slice}
Given a program $P$ and a slicing criterion $\langle s,v \rangle$, $S$ is the \textit{weak static backward slice} of $P$ with respect to $SC$ if $S$ fulfils the following properties:
\begin{enumerate}
\item $S$ is an executable program.
\item $S \subseteq P$, or $S$ is the result of removing 0 or more statements from $P$.
\item For any possible input, $\mathit{seq}(P, s, v)$ is a prefix of $\mathit{seq}(S, s, v)$.
\end{enumerate}
\end{definition}
Both Definition~\ref{def:strong-slice} and Definition~\ref{def:weak-slice} are
used throughout the literature.
Most publications do not differentiate them, as they work with one of them without acknowledging the other variant.
Therefore, although the definitions come from different authors, the \textit{weak} and \textit{strong} nomenclature employed throughout this thesis originates from a control dependence analysis by Danicic~\cite{DanBHHKL11}, where slices that produce the same output as the original are named \textit{strong}, and those where the original is a prefix of the slice, \textit{weak}.
Different applications of program slicing use the option that fits their needs, though \textit{weak} is used if possible, because the resulting slices are smaller statement-wise, and the algorithms used tend to be simpler.
Of course, if the application of program slices requires the slice to behave exactly like the original program, then \textit{strong} slices are the only option.
As an example, debugging uses weak slicing, as it does not matter what the program does after reaching the slicing criterion, which is typically the point where an error has been detected.
In contrast, program specialization requires strong slicing, as it extracts features or computations from a program to create a smaller, standalone unit which performs in the exact same way.
Along the thesis, we indicate which kind of slice is produced with each problem detected and technique proposed.
\begin{example}[Strong, weak and incorrect slices]
Consider table~\ref{tab:slice-weak}, which displays the sequence of values obtained with respect to different slices of a program and the same slicing criterion.
The first row stands for the original program's sequence of values, which computes $3!$.
Slice A's sequence of values is identical to the original and therefore it is a strong slice.
Slice B's sequence does not stop after producing the same first 3 values as the original: it is a weak slice. An instruction responsible for stopping the loop may have been excluded from the slice.
Slice C is incorrect, as the sequence differs from the original program in the second column. It seems that some dependence has not been accounted for and the value is not updating.
\begin{table}
\centering
\begin{tabular}{r | r | r | r | r | r }
% Evaluation Number & \textbf{1} & \textbf{2} & \textbf{3} & \textbf{4} & \textbf{5} \\ \hline
Original program & 1 & 2 & 6 & - & - \\ \hline
Slice A & 1 & 2 & 6 & - & - \\ \hline
Slice B & 1 & 2 & 6 & 24 & 120 \\ \hline
Slice C & 1 & 1 & 1 & 1 & 1 \\
\end{tabular}
\caption{Sequence of values obtained for a certain variable of the original program and three different slices A, B and C for a particular input.}
\label{tab:slice-weak}
\end{table}
\end{example}
\subsection{Computing program slices with the system dependence graph}
There exist multiple program representations, data structures and algorithms that can be used to compute a slice, but the most efficient and broadly used data structure is the \textit{system dependence graph} (SDG), introduced by Horwitz et al. \cite{HorRB90}.
It is computed from the program's source code, and once built, a slicing criterion is chosen and mapped on the graph, then the graph is traversed using a specific algorithm, and the slice is obtained.
Its efficiency relies on the fact that, for multiple slices performed on the same program, the graph generation process is only performed once.
Performance-wise, building the graph has quadratic complexity ($\mathcal{O}(n^2)$), and its traversal to compute the slice has linear complexity ($\mathcal{O}(n)$); both with respect to the number of statements in the program being sliced.
The SDG is a directed graph, and as such it has a set of nodes, each representing a statement in the program---barring some auxiliary nodes introduced by some approaches---and a set of directed edges, which represent the dependencies among nodes.
Those edges represent several kinds of dependencies: control, data, calls, parameter passing, summary.
To create the SDG, first a \textit{control flow graph} (CFG) is built for each method in the program, some dependencies are computed based on the CFG.
With that data, a new graph representation is created, called the \textit{program dependence graph} (PDG) \cite{OttO84}.
Each method's PDG is then connected to form the SDG.
For a simple visual example, see Example~\ref{exa:create-sdg} below, which briefly illustrates the intermediate steps in the SDG creation. The whole process is explained in detail in section~\ref{sec:first-def-sdg}.
Once the SDG has been created, a slicing criterion can be mapped on the graph and the edges are traversed backwards starting.
The process is performed twice, the first time ignoring a specific kind of edge, and the second, ignoring another kind.
Once the second pass has finished, all the nodes visited form the slice.
\begin{example}[The creation of a system dependence graph]
\label{exa:create-sdg}
Consider the code provided in Figure~\ref{fig:create-sdg-code}, where a simple Java program containing two methods (\texttt{main} and \texttt{multiply}) is displayed.
\begin{figure}[h]
\begin{lstlisting}
void main() {
multiply(2, 3);
}
int multiply(int x, int y) {
int result = 0;
while (x > 0) {
result += y;
x--;
}
System.out.println(result);
return result;
}
\end{lstlisting}
\caption{A simple Java program with two methods.}
\label{fig:create-sdg-code}
\end{figure}
Figure~\ref{fig:create-sdg-cfg} contains one CFG per method. Each CFG has a unique source node (without incoming edges) and a unique sink node (without outgoing edges), named ``Enter'' and ``Exit''. In between, the statements are structured according to all possible executions that could happen according to Java's semantics.
\begin{figure}[h]
\centering
\includegraphics[width=0.6\linewidth]{img/multiplycfg}
\caption{The control flow graphs for the code in Figure~\ref{fig:create-sdg-code}.}
\label{fig:create-sdg-cfg}
\end{figure}
Next is Figure~\ref{fig:create-sdg-pdg}, which is a reordering of the CFG's nodes according to the dependencies between statements: the PDG. Finally, both PDGs are connected into the SDG.
\begin{figure}
\centering
\includegraphics[width=\linewidth]{img/multiplypdg}
\includegraphics[width=\linewidth]{img/multiplysdg}
\caption{The program dependence graphs (above) and system dependence graph (below) generated from the code in Figure~\ref{fig:create-sdg-code}.}
\label{fig:create-sdg-pdg}
\end{figure}
\end{example}
\subsection{Program slicing metrics}
In the area of program slicing, there exist many slicing techniques and tools implementing them.
This fact has created the need to classify them by defining a set of metrics.
These metrics are commonly associated to some features of the generated slices, or to the resources used by the slicing tool.
The following list details the most relevant metrics considered when evaluating a program slice:
\begin{description}
\item[Completeness.] The solution includes all the statements that affect the slicing criterion. This is the most important feature, and almost all techniques and implemented tools set to achieve at least the generation of complete slices. There exists a trivial way of achieving completeness, by including the whole program in the slice.
\item[Correctness.] The solution excludes all statements that do not affect the slicing criterion. Most solutions are complete, but the degree of correctness is what sets them apart, as solutions that are more correct will produce smaller slices, which will execute fewer instructions to compute the same values, decreasing the executing time and complexity.
\item[Features covered.] Which features (polymorphism, global variables, arrays, etc.), programming languages or paradigms a slicing tool is able to cover. There are slicing tools (publicly published or commercially available) for most popular programming languages, from C++ to Erlang. Some slicing techniques only cover a subset of the targeted language, and as such are less useful, but can be a stepping stone in the betterment of the field. There also exist tools that cover multiple languages or that are language-independent \cite{BinGHI14}. A small set-back of language-independent tools is that they are not as efficient in other metrics.
\item[Performance.] Speed and memory consumption for the graph generation and slice creation. As previously stated, slicing is a two-step process: building a graph and traversing it, with the first process being quadratic and the second lineal (in time). Proposals that build upon the SDG try to keep traversal linear, even if that means making the graph bigger or slowing down its building process.
Though this metric may not seem as important as others, program slicing is not a simple analysis. On top of that, some applications of software slicing like debugging constantly change the program and slicing criterion, which makes faster slicing software preferable for them.
Regarding memory consumption, it is not currently a problem, given that the amount available in most workstations and servers is enough to run any slicing algorithm. It could become a concern in big programs with millions of lines of code, or in embedded systems, where memory is scarce.
\end{description}
\subsection{Variations and applications of program slicing}
As stated before, there are many uses for program slicing: program specialization, software maintenance, code obfuscation... but there is no doubt that program slicing is first and foremost a debugging technique.
Program slicing can also be performed with small variations on the algorithm or on the meaning of ``slice'' and ``slicing criterion'', so that it answers a slightly or totally different question.
Each variation of program slicing answers a different question and serves a different purpose:
\begin{description}
\item[Backward static.] Used to obtain the lines that affect the slicing criterion,
normally used on a line which contains an incorrect value, to track down
the source of the bug.
\item[Forward static.] Used to obtain the lines affected by the slicing criterion,
used to perform software maintenance: when changing a statement, slice the program w.r.t. that statement to discover the parts of the program that will be affected by the change.
\item[Chopping.] Given two slicing criteria, it obtains the intersection between the statements affected by the first criterion and the statements that affect the second criterion. It is mainly used for debugging applications.
\item[Dynamic.] Can be combined with any of the previous variations, and
limits the slice to an execution history, only including statements that
have run in a specific execution. The slice produced is much smaller and
useful, but must be recomputed each time. It can be used for debugging when the input values that cause the error are known.
\item[Quasi-static.] In this slicing variant, some input values are given, and some are left
unspecified: the result is a slice sized between the small dynamic slice and
the general but bigger static slice. It can be specially useful when
debugging a set of function calls which have a specific static input for
some parameters, and variable input for others.
\item[Simultaneous.] Similar to dynamic slicing, but considers multiple
executions instead of only one. It is another middle ground between static and dynamic slicing, similarly to quasi-static slicing.
Likewise, it can offer a slightly bigger slice than pure dynamic slicing while keeping the scope focused on the slicing criterion and the set of executions.
\end{description}
There exist many more, which have been detailed in surveys of the field, such as \cite{Sil12}.
\section{Exception handling}
\label{sec:intro-exception}
Exception handling is common in most modern programming languages. It generally consists of a few new instructions used to modify the normal execution flow and later return to it. Exceptions are used to react to an abnormal program behaviour (controlled or not), and either solve the error and continue the execution, or stop the program gracefully.
\subsection{Exception handling in Java}
In our work we focus on the Java programming language, so in the following, we describe the elements that Java uses to represent and handle exceptions:
\begin{description}
\item[Throwable.] A type that encompasses all the exceptions or errors
that may be thrown. Its two main implementations are \texttt{Error} for internal errors in the Java Virtual Machine and \texttt{Exception} for normal errors. The first ones are generally not caught, as they indicate a critical internal error, such as running out of memory, or overflowing the stack. The second kind encompasses the rest of exceptions that occur in Java.
All exceptions can be classified as either \textit{unchecked}
(those that extend \texttt{RuntimeException} or \texttt{Error}) or
\textit{checked} (all others, may inherit from \texttt{Throwable}, but typically they do so from \texttt{Exception}). Unchecked exceptions may be thrown anywhere without warning, whereas
checked exceptions, if thrown, must be either caught in the same method or declared in the method header.
\item[throws.] A statement that activates an exception, altering the normal
control-flow of the method. If the statement is inside a \texttt{try}
block with a \texttt{catch} statement for its type or any super type, the
control flow will continue in the first statement inside the \texttt{catch} statement.
Otherwise, the method is exited and the check performed again, until
either the exception is caught or the last method in the stack
(the \texttt{main} method) is popped, and the execution of the program ends
abruptly.
\item[try.] This statement contains a block of statements and one
or more \texttt{catch} statement and/or a \texttt{finally} statement.
All exceptions thrown in the statements contained or any methods called will be processed by the list of \texttt{catch} statements. If no \texttt{catch} matches the type of the exception, the exception propagates to the \texttt{try} block that contains the current one, or, in its absence, the method that called the current one.
\item[catch.] Contains two elements: a variable declaration, whose type must extend from \texttt{Throwable}, and a block of statements to be executed when an exception of a matching type is thrown.
The type of a thrown exception $T_1$ matches the type of a \texttt{catch} statement $T_2$ if one of the following is true: (1) $T_1 = T_2$, (2) $T_1~\textnormal{extends}~T_2$, (3) $T_1~\textnormal{extends}~T \wedge T~\textnormal{matches}~T_2$.
\texttt{catch} statements are processed sequentially, although their order does not matter, due to the restriction that each type must be placed after all of its subtypes.
When a matching \texttt{catch} is found, its block is executed and the rest are ignored.
Variable declarations may be of multiple types \texttt{(T1|T2 e)}, when two unrelated types of exception must be caught and the same code executed for both.
If there is an inheritance relationship, the parent suffices.\footnotemark
\item[finally.] Contains a block of statements that will always be executed, no matter what, if the \textit{try} is entered.
It is used to tidy up, for example closing I/O streams. The \texttt{finally} statement can be reached in two ways:
with an exception pending---thrown in \texttt{try} and not captured by
any \texttt{catch}, or thrown inside a \texttt{catch}---or without it
(when the \texttt{try} or \texttt{catch} end successfully). After
the last instruction of the block is executed, if there is an exception
pending, control will be passed to the corresponding \texttt{catch} or
the program will end. Otherwise, the execution continues in the next
statement after the \texttt{try-catch-finally} block.
\end{description}
\footnotetext{Only available from Java 7 onward. For more details, see \url{https://docs.oracle.com/javase/7/docs/technotes/guides/language/catch-multiple.html} (retrieved November 2019).}
\subsection{Exception handling in other programming languages}
\label{sec:exception-others}
In almost all programming languages, errors can appear (either through the
developer, the user or the system's fault), and must be dealt with. Most of the
popular object--oriented programming languages feature some kind of error system, which normally
very similar to Java's exceptions. In this section, we will perform a small
survey of the error-handling techniques used on the most popular programming
languages. The list of languages to be analysed has been extracted from the results of a survey performed by the
programming Q\&A website Stack Overflow\footnote{\url{https://stackoverflow.com}}. The survey contains a
question about the technologies used by professional developers in their work,
and from that list we have extracted those languages with more than $5\%$ usage
in the industry. Table~\ref{tab:popular-languages} displays the list and its
source. All languages displayed there feature an exception system similar to Java's, except for Bash, Assembly, VBA, C and Go\footnotemark.
\footnotetext{PowerShell only features an exception system since version 2.0, released alongside Windows 7.}
\begin{table}
\begin{minipage}{0.6\linewidth}
\centering
\begin{tabular}{r | r }
\textbf{Language} & $\%$ usage \\ \hline
JavaScript & 69.7 \\ \hline
HTML/CSS & 63.1 \\ \hline
SQL & 56.5 \\ \hline
Python & 39.4 \\ \hline
Java & 39.2 \\ \hline
Bash/Shell/PowerShell & 37.9 \\ \hline
C\# & 31.9 \\ \hline
PHP & 25.8 \\ \hline
TypeScript & 23.5 \\ \hline
C++ & 20.4 \\ \hline
\end{tabular}
\end{minipage}
\begin{minipage}{0.39\linewidth}
\begin{tabular}{r | r }
\textbf{Language} & $\%$ usage \\ \hline
C & 17.3 \\ \hline
Ruby & 8.9 \\ \hline
Go & 8.8 \\ \hline
Swift & 6.8 \\ \hline
Kotlin & 6.6 \\ \hline
R & 5.6 \\ \hline
VBA & 5.5 \\ \hline
Objective-C & 5.2 \\ \hline
Assembly & 5.0 \\ \hline
\end{tabular}
\end{minipage}
% The caption has a weird structure due to the fact that there's a footnote
% inside of it.
\caption[Commonly used programming languages]{The most commonly used
programming languages by professional developers\protect\footnotemark}
\label{tab:popular-languages}
\end{table}
\footnotetext{From a survey on software developers by StackOverflow. Source: \url{https://insights.stackoverflow.com/survey/2019/\#technology-\_-programming-scripting-and-markup-languages} (retrieved November 2019).}
The exception systems that are similar to Java are mostly all the same,
featuring a \texttt{throw} statement (i.e. \texttt{raise} in Python), \texttt{try-catch}-like
structure, and most include a \texttt{finally} statement that may be appended to \texttt{try} blocks.
The difference resides in the value passed by the exception.
In programming languages with inheritance and polymorphism, the value is restricted to any type that extends a generic error type (e.g. \texttt{Throwable} in Java). The exceptions are filtered using types.
In languages without inheritance, the value is an arbitrary one (e.g.
JavaScript, TypeScript), with the exceptions being filtered using a boolean condition or pattern to be matched (e.g. JavaScript). In both cases
there exists a way to indicate that all possible exceptions should be caught, regardless
of type and content.
Regarding the languages that do not offer an exception handling mechanism similar to Java's, error-handling is covered by a variety of systems, which are briefly detailed below.
\begin{description} % bash, vba, C and Go exceptions explained
\item[Bash.] The popular Bourne Again SHell features no exception system, apart
from the user's ability to check the return code from the last statement
executed. Traps can also be used to capture erroneous states and tidy up all
files and environment variables before exiting the program. In essence, traps allow the
programmer to react to a user or system--sent signal, or an exit run from
within the Bash environment. When a trap is activated, its code run, and the
signal does not proceed and stop the program. This does not replace a fully
featured exception system, but \texttt{bash} programs tend to be short, with programmers preferring the efficiency of C or the commodities of
other high--level languages when the task requires it.
\item[VBA.] Visual Basic for Applications is a scripting programming language
based on Visual Basic that is integrated into Microsoft Office to automate
small tasks, such as generating documents from templates, making advanced
computations that are impossible or slower with spreadsheet functions, etc.
The only error--correcting system it has is the directive \texttt{On Error
$x$}, where $x$ can be 0---lets the error crash the program---,
\texttt{Next}---continues the execution as if nothing had happened---or a
label in the program---the execution jumps to the label in case of
error. The directive can be set and reset multiple times, therefore creating
artificial \texttt{try-catch} blocks, but there is no possibility of
attaching a value to the error, lowering its usefulness.
\item[C.] In C, errors can also be controlled via return values, but some
instructions featured in it can be used to create a simple exception system.
\texttt{setjmp} and \texttt{longjmp} are two instructions which set up and
perform inter--function jumps. The first makes a snapshot of the call stack
in a buffer, and the second returns to the position where the buffer was
safe, destroying the current state of the stack and replacing it with the
snapshot. Then, the execution continues from the evaluation of
\texttt{setjmp}, which returns the second argument passed to
\texttt{longjmp}. Example~\ref{exa:exceptions-c} shows this system in action.
\begin{example}[User-built exception handling system in C] \ \\
\label{exa:exceptions-c}
\begin{figure}[h]
\begin{minipage}{0.45\linewidth}
\begin{lstlisting}[language=C]
int main() {
if (!setjmp(ref)) {
res = safe_sqrt(x, ref);
} else {
// Handle error
printf /* ... */
}
}
\end{lstlisting}
\end{minipage}
\begin{minipage}{0.54\linewidth}
\begin{lstlisting}[language=C]
double safe_sqrt(double x, int ref) {
if (x < 0)
longjmp(ref, 1);
return /* ... */;
}
\end{lstlisting}
\end{minipage}
\caption{A simple \texttt{main} method (left) with an emulated \texttt{try-catch} and a method that computes a square root (left), emulating a \texttt{throw} statement if the number is negative.}
\label{fig:exceptions-c}
\end{figure}
Consider Figure~\ref{fig:exceptions-c}: in the \texttt{main} function, line 2 will be executed twice: first when
it is normally reached---returning 0 and continuing in line 3---and the second when line 3 in
\texttt{safe\_sqrt} is run, returning the second argument of \texttt{longjmp},
and therefore entering the else block in the \texttt{main} method.
\end{example}
\item[Go.] The programming language Go is the odd one out in this section, being a
modern programming language without exceptions, though it is an intentional
design decision made by its authors\footnotemark. The argument made was that
exception handling systems introduce abnormal control--flow and complicate
code analysis and clean code generation, as it is not clear the paths that
the code may follow. Instead, Go allows functions to return multiple values,
with the second value typically associated to an error type. The error is
checked before the value, and acted upon. Additionally, Go also features a
simple panic system, with the functions \texttt{panic}---throws an
exception with a value associated---, \texttt{defer}---runs after the
function has ended or when a \texttt{panic} has been activated---and
\texttt{recover}---stops the panic state and retrieves its value. The
\texttt{defer} statement doubles as catch and finally, and multiple
instances can be accumulated. When appropriate, they will run in LIFO
(Last In--First Out) order.
\item[Assembly.] Assembly is a representation of machine code, and each computer architecture has its own instruction set, which makes an analysis impossible. In general, though, no unified exception handling is provided: each processor architecture may provide its own system or not. As with previous entries on this list, the exception system can be emulated, in this case with the low-level instructions commonly available in most architectures.
\end{description}
\footnotetext{For more details on Go's design choices, see \url{https://golang.org/doc/faq\#exceptions} (retrieved November 2019).}
% vim: set noexpandtab:tabstop=2:shiftwidth=2:softtabstop=2:wrap