Legacy of Void*

23
Exiting the Dark Ages of Void* with C++11

description

 

Transcript of Legacy of Void*

Page 1: Legacy of Void*

Exiting the Dark Ages of Void* with C++11

Page 2: Legacy of Void*

*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

Page 3: Legacy of Void*

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

Page 4: Legacy of Void*

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)

Page 5: Legacy of Void*

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++

Page 6: Legacy of Void*

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.

Page 7: Legacy of Void*

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!

Page 8: Legacy of Void*

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.

Page 9: Legacy of Void*

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.

Page 10: Legacy of Void*

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.”

Page 11: Legacy of Void*

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.

Page 12: Legacy of Void*

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.

Page 13: Legacy of Void*

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

Page 14: Legacy of Void*

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)

Page 15: Legacy of Void*

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.

Page 16: Legacy of Void*

“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

Page 17: Legacy of Void*

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

Page 18: Legacy of Void*

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;

}

Page 19: Legacy of Void*

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.

Page 20: Legacy of Void*

“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)

Page 21: Legacy of Void*

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

Page 22: Legacy of Void*

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

Page 23: Legacy of Void*

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”