summaryrefslogtreecommitdiff
path: root/a6/au_BentBisballeNyeng_A6.tex
diff options
context:
space:
mode:
Diffstat (limited to 'a6/au_BentBisballeNyeng_A6.tex')
-rw-r--r--a6/au_BentBisballeNyeng_A6.tex117
1 files changed, 94 insertions, 23 deletions
diff --git a/a6/au_BentBisballeNyeng_A6.tex b/a6/au_BentBisballeNyeng_A6.tex
index ad4cc0d..c6ad150 100644
--- a/a6/au_BentBisballeNyeng_A6.tex
+++ b/a6/au_BentBisballeNyeng_A6.tex
@@ -90,9 +90,11 @@ along with not supporting exceptions and run-time type
information\cite{craig}.
Working with the resulting small sub-set of the available components,
-however, is not well suited for making contemporary C++ applications.
+however, is not well suited for making contemporary C++ applications;
+too many core components are missing so be able to really call it
+contemporary.
The ideal solution would be to find ways to be able to use all (or at
-least most) features, but with a potential known set of restictions or
+least more) features, but with a potential known set of restictions or
limitations.
\section{Method}
@@ -100,28 +102,73 @@ In the following, 3 methods for managing memory allocations will be
investigated, and their suitability for real-life applications be
evaluated:
\begin{itemize}
-\item Using Custom Allocators for the STL components that supports it.
-\item Overloading \texttt{new}/\texttt{delete} to use stack allocated
- memory instead of the free-store for all allocation.
\item Support from the compiler to fail compilation if an
unintentional \texttt{new} or \texttt{delete} is being called,
at least preventing accidental allocations.
+\item Using Custom Allocators for the STL components that supports it.
+\item Overloading \texttt{new}/\texttt{delete} to use stack allocated
+ memory instead of the free-store for all allocation.
\end{itemize}
-Each of the three will be evaluated with large lambda
-captures, \texttt{std::vector} allocation and some simple co-routines.
-The epxeriments are done on a linux PC using the gcc-11.2 compiler.
+\noindent{}Each of the three will be evaluated with
+\texttt{std::string}, \texttt{std::vector}, \texttt{std::function} and
+co-routines.\\
+The experiments are done on a linux PC using the gcc-11.2 compiler.
\section{Experiments}
-
-----------------------------------------
-
-
-No access to MMU, implicitly, prohibits calls to delete after
-initialization phase. Otherwise this will lead to memory fragmentation
-which again might lead to free-store depletion and ultimately
-application failure.
+This section describes the work done during the three experiments
+along with any numerical or analytical results found.
+
+\subsection{Detecting Allocations}\label{detect}
+
+Searches on the Internet{\tm} has identified no ways of instructing
+the compiler that ``no allocations allowed, fail if one is made''.
+The reworked free-standing specification might make this possible in
+the future, similarly to how exceptions and run-time type information
+can be disabled with \texttt{-fno-exceptions} and \texttt{-fno-rtti}.
+There exists a \texttt{-ffreestanding} argument, but this follows the
+old (current) definition of free-standing and as such allows
+dynamic allocation so it cannot be used.
+
+Some constructs have built-in optimizations that make them store their
+data in local members, instead of on the free-store through a pointer,
+until som limit is reached making it possible to use for
+example \texttt{std::string}s or \texttt{std::function}s as long as
+they don't require more than $N$ bytes, where $N$ is a compiler
+dependent.
+
+To detect if a free-store allocation is done a simple overload
+of \texttt{new} and \texttt{delete} can be done, which simply throws
+an exeption if called.
+This will lead to a run-time error and not a compile-time one as would
+have been the ideal solution, but at least it can assists in finding
+the $N$ for a specific compiler.
+
+This experiment can be found in the \texttt{noalloc.cc} file. The
+following table shows the impirically deduced sizes of $N$ wherever
+SSO/SBO is available along with comments about the general component
+behaviour.\\
+
+\noindent\begin{tabular}{| l | c | l |}
+\hline
+Component & $N$ & Comments \\
+\hline
+\texttt{std::string} & $16$ & Exception propagates to caller. \\
+\texttt{std::vector} & N/A & No SBO, exception propagates to caller. \\
+\texttt{std::function} & $16$ & Exception doesn't seem to propagate to
+caller (possible gcc bug). \\
+co-routine & N/A & No SBO, exception propagates to caller. \\
+\hline
+\end{tabular}
+
+\subsection{Custom Allocator}
+
+\begin{verbatim}
+Write allocator that uses stack-buffer and fails when depleted and try
+it out (monotonic allocations)
+List the components that supports it
+\end{verbatim}
Writing a custom allocator is only a solution to a sub-set of the
allocations in an application, for example if all allocations are
@@ -132,6 +179,17 @@ But for most applications (or at least most parts on an application)
this is not the case, and therefore others means need to be taken into
use.
+std::string works, using basic_string, but is a bit clumsy
+
+std::vector works beautifully
+
+std::function as of c++17 can no longer be used with allocators
+
+Adding new operator to promise_type:
+https://en.cppreference.com/w/cpp/language/coroutines#Dynamic_allocation
+
+
+\subsection{Use \texttt{new} with Stack Buffer}
The most common way of addressing this, is simply to only use stack
allocation, or store all objects in as static globals.
But in certain areas of the C++ language dynamic allocation might
@@ -141,13 +199,26 @@ one example, but even more devious is the capture clause of a
lambda, which might allocate extra memory, if more than $N$ members
are captured, where $N$ is compiler dependent.
-No way of telling the compiler that ``no allocations allowed, fail if
-one is made'' exists, but one could wish for such a mechanism in the
-wake of the ``free-standing C++'' subset work.
-One thing is to prohibit use of language constructs that are
-guaranteed to allocate, but quite another is to allow using constructs
-in ways that doesn't make them allocate.
-This, I think, is not part of the ``free-standing C++'' work.
+Expanding on the overloaded \texttt{new} and \texttt{delete} from
+section \ref{detect} a mechanism for using a stack-buffer for exactly
+one call to \texttt{new} is made, looking something like this:
+\begin{lstlisting}[language=C++]
+void foo()
+\end{lstlisting}
+
+Object owning the buffer and registering itself with the next call to
+new.
+
+Scope of the stack object must be the same as the object using
+it. Compiler does not help with that so this must be done by
+convention.
+
+\section{Summing Up}
+
+Can be done, but is by no means elegant and can in some solution be
+downright dangerous.
+But if this is the price to pay to be able to use co-routines in
+microcontrollers perhaps it is worth it none the less.
\printbibliography