Legacy of Void*
-
Upload
adam-crain -
Category
Software
-
view
497 -
download
2
description
Transcript of Legacy of Void*
Exiting the Dark Ages of Void* with C++11
*YOU* are full of bullshit.
C++ is a horrible language. It's made more horrible by
the fact that a lot of substandard programmers use it, to
the point where it's much much easier to generate total
and utter crap with it. Quite frankly, even if the choice of
C were to do *nothing* but keep the C++ programmers
out, that in itself would be a huge reason to use C.
-Linus Torvalds (2007)
http://harmful.cat-v.org/software/c++/linus
What is an embedded system?
Well, a lot of different things, but generally speaking:
● Dedicated to a single purpose● Minimalist approach to reduce cost● “Always on”● Has stiff reliability requirements● uses safeguards like watchdogs for recovery
Software selection based on hardware?
Bare metal:
ATtiny85, 8K of
flash
512 byte of SRAM
512 bytes of
EEPROM
general-purpose OS(hopefully ruggedized)
● Bare metal or microkernel / RTOS
● Lots of C!
(ok, NASA uses some ADA)
Myths about C++ in embedded systems
● C++ code is slow compared to C● C++ produces binaries too big for embedded systems● Templates create too much code “bloat”● Dynamic dispatch is slow. Virtual functions are too
“heavyweight”.● C++ is synonymous with dynamic allocation● It’s too hard to port C++ to other architectures● STL is the devil for embedded systems, therefore you shouldn’t
use C++
Myth #1: C++ is slow
Truth: If you use C++ as “C with classes” you willget virtually indistinguishableperformance. Other lightweight features add minimal overhead.
Certain features of C++ can be too slow or otherwise unsuitable for certain embedded applications.
Myth #2: C++ Binaries Are Too Big
Truth:Using a reasonable subset of features leads to similar binary files sizes.
Frequently, higher level abstractions can reduce copy/paste coding.
libstdc++ is big. It’s also frequently not available!
Myth #3: Templates create too much code bloat
Truth:
If you factor template independent code outside of your templates, you can minimize this effect. Every good C++ programmer knows this.
Extensive use of macros in C produce bloat just as easily, with more obfuscation, and with less type safety.
Myth #4: Dynamic Dispatch is “Slow”
Truth: The overhead from virtual functions & vtables is actually pretty acceptable for almost all applications.
● one vtable per class (not per object)● one pointer to the vtable per object● one dereferencing operation per call (a couple cycles on most hardware)
Virtual functions can be abused like any language feature. However, abstraction via interfaces (abstract classes in C++) is too powerful a tool for building APIs and testing code to ignore.
Lulz
http://freshbsd.org/commit/openbsd/8a6680833c42bde7de74b9ddb70bbad193c5359b
“Why do we hide from the OpenSSL police, dad?”
“Because they're not like us, son. They use macros to wrap stdio routines, for an undocumented (OPENSSL_USE_APPLINK) use case, which only serves to obfuscate the code.”
Myth #5: C++ == dynamic allocation
Truth:There is nothing about C++ that forces you to use dynamic allocation.
If you don’t like the STL, don’t use it. The STL is a library not the language.
Myth #6: C++ leads to non-portable code
Truth:
This used to be true. C++ compilers have made enormous strides in recent years for a number of reasons. Clang and GCC are now driving progress, and even MSVC++ is quite compliant to the standard.
If you develop with multiple compilers frequently and avoid platform extensions, you’ll have excellent portability. C++ abstractions make it easier to separate platform-specific code.
Lulz
“I'm glad to know that Ultrix CC has a bug optimizing switch() statements lacking an explicit `case 0:' construct. But Ultrix has been dead for more than 15 years, really. Don't give it any reason to move out of its coffin.”
http://freshbsd.org/commit/openbsd/111423c9d25cd2128223242f0a3d7dcaa9acb3b5
Why is C++ “better now”?
● Renewed interest in native languages● Clang (C-family front-end compiler for LLVM) has been pushing
GCC to improve● Coopetition between Intel/Microsoft/OSS tools to be “conformant”● Many embedded vendors have switched from proprietary
toolchains to GCC-based tools (expect even more to switch to Clang/LLVM)
What is Clang/LLVM?LLVM is a language-agnostic compiler architecture. It separates language-specific lexing / early-stage compilation from the translation & optimization of specific targets.
Interested in creating a new language? No problem, it will easily be able to target different architectures if your compile to LLVM.
Interested in adding support for a new architecture? Great, you only have to translate LLVM instructions to your target.
“Lightweight” C++ for MCUs (MISRA?)
Free (no significant overhead vs. C)● Classes● Constructors / destructors & OOP modularity● Single inheritance● C++11 lambdas, constexpr, access modifiers● templates (if factored appropriately)
Cheap:● Virtual methods
Costly to some metric (performance / determinism / code size / runtime / memory / etc)● dynamic allocation● Virtual inheritance● Run-time type information (RTTI == dynamic_cast<> & typeid)● Exceptions
How can C++ improve robustness/security?
● More powerful abstractionso private members - data hiding / encapsulationo const correctness - enforce immutabilityo deterministic destructors - guaranteed resource release
● Wrappers to that mediate access to dangerous resourceso e.g. buffer views (wrappers)
● Better type-safety means that you make fewer assumptions in code.
● Powerful design patterns can be applied to encourage better practices
Simple pattern, big effect: RAII
The Problem (pseudo code in C)
int stupidprefix_some_function_that_returns_error_code(.... arguments){
int err = 0;stupidprefix_acquire_resource(&resource);stupidprefix_do_stuff_with_resource(&resource);// … yada yada lots of code branches that require resource // from which you can’t return (hint: use GOTO)
CLEANUP:stupidprefix_release_resource(&resource);return err;
}
C++ version w/ RAIInamespace kickasswehavenamespaces{
int some_function_that_returns_error_code(.... arguments){
Acquisition mediator(raw_resource);do_stuff_with_resource(mediator);
//... Code branches //... Any return calls mediator’s destructor
return 0;}
}
The act of acquiring a resource guarantees its release.
“Resource Acquisition Is Initialization”.
Java doesn’t even have an acceptable substitute.
C# has “using” statement.
“embeddable” C++11 features● static_assert - Compile time assertions complete with custom
compiler error messages. Ensure that your library is being configured with safe constants / types.
● constexpr - Compile time calculations (yet another Turing complete metaprogramming language)
● Access modifiers for method (override final)
What specific design aims guided the committee?
“Improve performance and ability to work directly with hardware -- make C++ even better for embedded systems programming and high-performance computation.”
http://www.stroustrup.com/C++11FAQ.html
So, dnp3 on Atmega2560?
CPU: 8-bit AVR
Max. Operating Freq. (MHz): 16 MHz
SRAM: 8K
Flash (Kbytes): 256 Kbytes
https://github.com/automatak/dnp3/blob/2.0.x/embedded/atmelavr/demooutstation/main.cpp
AVR DNP3 Demo● C++11 using GCC 4.8.1 and 8-bit AVR backend● USART only at this point● Level 3 stack - more feature-rich than many RTUs / IEDs● All statically allocated● All interrupt based event-loop● Makes use of AVR sleep mode
● SAv5? maybe possible? Definitely on ARM Cortex (Arduino DUE)● Community members have been prototyping on TI ARM & PIC● Need an interesting I/O shield to make a real “IED”