Bitesize Modern C++: enum class

June 18th, 2015

Enumerated types in C++ give a trivial simulation of symbolic types – that is, objects whose instances have unique, human-readable values. In C++ enumerations are essentially named integers that are either assigned values implicitly by the compiler or explicitly by the programmer (or a combination of both)

C++ enum types inherit their semantics from C with some additions:

  • enum objects are now first-class types
  • enums may be implicitly converted to integers; but the reverse is not true

image

Another characteristic illustrated in the above code is the need for all enumerated symbols to be (globally) unique. This can be both frustrating and difficult to maintain for larger systems.

C++11’s enumeration classes provide strongly-typed enumerations.

An enum class, unlike the C++98 enum does not export its enumerator names into its enclosing scope, meaning different enum class objects can have the same enumerator value, without causing a name issue.

Also, enum class values cannot be implicitly converted to integers.

image

One of the more confusing aspects of C++98 enums was their size – although the type of an enum was defined (int) its size was implementation defined and required only to be a type big enough to hold the largest enumerated value. This means that an enumeration could be 8, 16, 32 or even 64 bits in size; and could change if new enum values were specified. This could (and probably has!) cause alignment issues in embedded systems.

We can now specify the underlying type of the enumeration (as long as it’s an integer type). The default is integer; as with C++98.

image

If the enum class type is to be used as a forward reference you can (must) provide the underlying type as part of the declaration.

image

More information

Can’t wait? Download the full set of articles as a PDF, here.

To learn more about Feabhas’ Modern C++ training courses, click here.

Bitesize Modern C++ : static_assert

June 4th, 2015

C’s assert library is a useful tool for catching invalid invariants (conditions that must hold true in order for your system to operate as specified) in your program. The big problem with assert is that it’s a run-time check; in many cases the best you can do  to recover from an assert failure is restart the system or put it into a quiescent state.

In a lot of cases the (faulty) invariants could be detected at compile-time but in C++98 there was no mechanism for doing so. The pre-processor has an assert-like mechanism – #error – but the pre-processor has no knowledge of your C++ code so it cannot evaluate program invariants.

In C++11 a compile-time assert mechanism was added: static_assert.

static_assert acts like run-time assert except that the checked-condition must be a constant-expression (that is, an expression that can be evaluated at compile-time); the checked-condition must be a boolean expression, or an expression that can be converted to a boolean.

image

The message string must be a string literal.  It cannot be a (compile-time) computed value (ignoring pre-processor stringification).

From C++17 the message will be optional.

 

More information

Can’t wait? Download the full set of articles as a PDF, here.

To learn more about Feabhas’ Modern C++ training courses, click here.

Bitesize Modern C++ : constexpr

May 21st, 2015

A constant expression is an expression that can be evaluated at compile-time. The const qualifier gives a weak guarantee of a constant expression – a const-qualified type may not be changed after initialisation but that does not guarantee it will be initialised at compile-time. For example:

image

C++11 introduces a strong form of constant expression, constexpr, which also expands the capabilities of compile-time evaluation.

constexpr objects

A constexpr variable is essentially the same as qualifying the type as const with the additional requirement that its initialiser(s) must be known at compile-time. Any object type that could be made const can be made a constexpr object.  As expected, the object must be initialised on definition.  Note that literals are, by definition, constant expressions.

image

Since constexpr types have their value known at compile-time they can be placed in read-only memory; and, for built-in types (and provided you don’t take their address) the compiler doesn’t even have to store the object. We’ll look at user-defined (class)types in a moment.

constexpr functions

So far, so what?

The real power of constant expressions comes from the fact that not only objects but functions may be qualified as constexpr.

A constexpr function is one that may be evaluated at compile-time; and hence used in the definition of other constant expressions:

image

Of course, there are some limitations with constexpr functions:

  • They must have exactly one return statement
  • They cannot have local variables
  • They cannot have conditional expressions
  • They cannot throw exceptions
  • They cannot include a goto statement
  • All parameters must be (capable of being) constexpr objects

Put simply, in order to be a constexpr function everything the function needs to be computed must be known at compile-time. Making a function a constant expression implies it is inline.

(Note: C++14 relaxes some of these requirements with respect to local variables and conditionals).

Marking a function as a constexpr doesn’t limit it to only be usable at compile-time. They may still be used at run time:

image

ROM-able types

The use of constexpr for functions extends to member functions, too. Marking a member function as a constexpr implicitly makes it a const function, meaning it cannot change any of the attributes of the class.

This is also true of constructors. Making a class’s constructor a constexpr allows objects of that type to themselves be constexpr objects.

image

Since everything required to construct the Rommable object is known at compile-time it can be constructed in read-only memory.

In order to be truly ROM-able there are some additional requirements we must satisfy (over and above the requirements for a constexpr function):

  • The class cannot have any virtual functions (virtual functions cannot be constant expressions)
  • The class cannot have a virtual base class
  • All base classes and all const members must be initialised by the constructor

 

More information

Can’t wait? Download the full set of articles as a PDF, here.

To learn more about Feabhas’ Modern C++ training courses, click here.

Bitesize Modern C++ : auto

May 8th, 2015

C++ is a statically-typed language, that is, you must explicitly declare the type of every object before use. The type of an object specifies

  • The amount of memory occupied
  • How the memory (bits) is interpreted
  • The operations allowable on the object

An object’s type is fixed at declaration – unless the programmer chooses to circumvent the type system using a cast.

Often for C++ objects specifying the type can be onerous:

image

C++11 allows automatic type-deduction to simplify the creation and maintenance of code.

The auto keyword has been appropriated from C (where it was a storage specifier indicating a local – ‘automatic’ – variable) that is almost never used.  From C++11 onwards auto now means ‘deduce the type of an object’

Let’s start with some simple (but not particularly useful) examples.

image

The compiler uses the type of the initialiser to establish the type of the new object. Note, the object still has a definitive (and fixed) type. Type-deduction does not lead to ‘duck typing’.

(As an aside, one might reasonably argue that there is very little benefit in auto-deducing built-in types; and, in fact, could even be less explicit to the reader)

To use auto the compiler must have the information to deduce the type (and therefore allocate memory). Therefore, there are some (obvious?) limitations to where auto can be used:

image

The mechanism used by the compiler for type-deduction is the same one used to deduce parameter types for template functions. Because of this, the object-type deduced for an auto object may not be exactly what the programmer expects.

The rules are as follows:

  • The deduced type will be a new object.
  • If the initialiser is a reference-to-object, the reference is ignored (since a reference is just an alias for an object).
  • Any const-volatile (cv)-qualifiers on the initialiser are ignored (since the cv-qualifiers are a property of the initialiser, not the new object).
  • Arrays are degenerated into pointer types.

image

We can cv-qualify the deduced type separately, if required. The cv-qualifiers are applied to the new object – after its type has been deduced.

image

If we reference-qualify the auto-deduced type the rules change:

  • The deduced type will now be a reference the initialiser object.
  • Any cv-qualifiers of the initialiser will be maintained on the deduced type (since a reference cannot be less restrictive than its referent; although it can be more restrictive).
  • If the initialiser is an array the deduced type is a reference-to-array type, not a pointer.

image

Returning to our original example, we can simplify the code (considerably) with the use of auto.

image

Additionally, the use of auto allows us a degree of flexibility in our code for future modifications:

image

More information

Can’t wait? Download the full set of articles as a PDF, here.

To learn more about Feabhas’ Modern C++ training courses, click here.

Bitesize Modern C++

May 7th, 2015

The C++11 standard marked a fundamental change to the C++ language. A range of new language constructs and library features were added and, as a result, new idioms were developed. Bjarne Stroustrup, originator of C++, referred to it as “feeling like a completely new language”.

In 2014 a revision of the standard was released with refinements to C++11 features and some new constructs, designed to improve the usability of the language; another revision is planned for 2017.

Traditionally, C++ programmers refer to their language version by the standard release year (so, C++98, C++03) but, as C++11 marked such a fundamental shift in the programming style of C++ (and as revisions are coming out more frequently) people are starting to refer to C++ post-2011 as ‘Modern C++’

In the embedded world Modern C++ has had comparatively little take-up, possibly due to a lack of embedded compiler support. Slowly, though, this is beginning to change.

There is a huge amount of material available on Modern C++. It has been explored, examined and dissected by experts for nearly five year. However, for the C++ programmer just starting to transition to Modern C++ a lot of this material can be somewhat overwhelming. For many it can be difficult to find a simple place just to start.

And that’s the idea behind these articles.

We wanted to present simple introductions to the new features in Modern C++ – ones that are useful for programmers currently using C++98. These are not the big, headline features – lambda expressions, move semantics, etc. – but the ‘little’ additions that can make you more productive and your programs more elegant and maintainable.

The other thing we wanted to avoid was TMI – Too Much Information. These articles are not meant to be definitive; they don’t explore every last quirk and corner-case. You won’t be an expert after reading these articles. Their purpose is simply to get you started; to give you a jumping-off place for all the excellent, detailed information out there.

For those who can’t wait the full set of articles will be available to download as a PDF

Enjoy!

The Rule of Zero

January 15th, 2015

In a previous article – ”The Rule of the Big Four (and a half)” we looked at resource management policies in C++.

Resource management is the general term for using the mechanisms in C++ to ensure that resources – files, dynamic memory, sockets, mutexes, etc – have their lifetimes automatically controlled so as to prevent resource leaks, deadlocks, etc. C++ refers to these mechanisms as RAII/RDID ( “Resource Acquisition Is Initialisation / Resource Destruction is Deletion”)

In this article we’ll have a look at a complementary guideline to help simplify your application code, without risking resource management issues – The Rule of Zero.

Read more »

The Rule of The Big Four (and a half) – Move Semantics and Resource Management

January 1st, 2015

In the previous article we looked at the issues of resource management in C++ and introduced “The Rule of The Big Three (and a half)”. In this article we’ll extend this concept by looking at the idea of move semantics, a feature introduced in C++11. Move semantics mean we’ll have to extend our rule to “The Rule of The Big Five” or, perhaps more correctly, “The Rule of The Big Four (and a half)”.

Read more »

The Rule of The Big Three (and a half) – Resource Management in C++

December 18th, 2014

The dynamic creation and destruction of objects was always one of the bugbears of C. It required the programmer to (manually) control the allocation of memory for the object, handle the object’s initialisation then ensure that the object was safely cleaned-up after use and its memory returned to the heap. Because many C programmers weren’t educated in the potential problems (or were just plain lazy or delinquent in their programming) C got a reputation in some quarters for being an unsafe, memory-leaking language.

C++ improved matters significantly by introducing an idiom known (snappily) as RAII/RRID – Resource Acquisition Is Initialisation / Resource Release Is Destruction*. The idiom makes use of the fact that every time an object is created a constructor is called; and when that object goes out of scope a destructor is called. The constructor/destructor pair can be used to create an object that automatically allocates and initialises another object (known as the managed object) and cleans up the managed object when it (the manager) goes out of scope. This mechanism is generically referred to as resource management.

In this article we’ll explore resource management in C++ and introduce “The Rule of The Big Three (and a half)”.

Read more »

Software Duct Tape – Binding the C++ Universe Together

December 4th, 2014

One of the cornerstones of object-oriented design is the concept of objects interacting by sending messages to form mechanisms – units of higher-order (or ‘emergent’) behaviour.

In order to send a message (in this case, invoke a member function) an object must have a ‘link’ to the target object. That link is formed by building in an association between the two classes as part of the type’s definition.

In this article we look at building associations between classes and forming run-time links so objects can communicate.

The basic principle

An association represents the ability of one object to send a message (invoke a function) of another. In order to do that the sending object must know the identity of the receiver.

The identity of an object is its address; therefore we must hold the address of the receiver. An association between two classes is therefore implemented as a pointer to that type.

We also need a ‘binding’ function to encapsulate the linking of the two objects.

Connected objects form a system

image

In a client-server relationship the client invokes the services of the server. The client sends messages to the server. That is, the client invokes the member functions of the server. This relationship is uni-directional. The server never calls the client’s member functions.

In a peer-to-peer relationship either object may invoke the operations on the other. That is, the relationship is bi-directional.

Note: Just because a member function returns a value does not make the relationship bi-directional. The association type is determined by who makes the member function calls, not the direction of data travel.

Client-Server 1:1 association

The simplest, and probably most common, form of association is the unidirectional client-server.

image

In this example the Positioner class is the client, with two (independent) server classes – Actuator and Sensor. Here the identities of the server objects are stored as pointers; the constructor is used as the binding function.

We form the link by binding the actual objects together at run-time. In this example we bind the Actuator object and the Sensor object by passing in the addresses of these objects to the Positioner constructor.

image

The Positioner can now invoke member functions on its associated objects by dereferencing its pointers.

Improving the interface

Since a reference is an alias for an (existing) object, taking the address of a reference is the same as taking the address of the original object.

image

Or, put another way: since a reference acts as an automatically-dereferenced (const) pointer, taking the address of a reference is semantically equivalent to:

&(*(&pos));

image

Passing by reference hides from the client the fact that the CameraStabiliser stores pointers internally. This is yet another form of encapsulation.

A quick aside: Why not use references for associations?

In this simple case you could – and many programmers advocate this – use a reference to the server object instead of a pointer. I prefer to use a pointer for a number of reasons:

  • A pointer specifies that I am holding the address (identity) of an object; references are a mechanism for efficient parameter passing in functions. Let’s use the language idioms correctly and consistently
  • Pointers can be used consistently for all association types; references can’t. See below for more on this.
  • Since references can’t be re-seated using a reference ‘fixes’ the association. There’s no way to associate objects differently later in the program. This precludes the ability to do substitution of specialised types at run-time. This dramatically limits the flexibility of your design.  You’re probably better off using a template instead.

While we’re talking about pointers: don’t be tempted to use smart pointers for associations. The problem with a smart pointer is that it’s designed for use with dynamically-allocated objects. As a client you can’t (and shouldn’t) know the storage specification of your server object. If the server object is stack-based when your association smart pointer goes out of scope it will try and call delete on the address of the object (for those who haven’t experienced this, trust me – it never ends well).

Associations are one of the very few valid uses of ‘raw’ pointers in a C++ program.

1:N unidirectional associations

When the association is one-to-many then a simple pointer does not suffice. We could use individual (named) pointers but this would be a clumsy solution (at best). In this case we use a std::array to hold the pointers (since the maximum number of Position objects is fixed, at 16).

image

The moveTo() function acts as a ‘bind’ function. It adds the address of the associated object to the track array.

image

Notice that in this case we can’t use references to hold the identity of the object because you can’t have an array of references.

1:* Unidirectional associations

It’s a relatively trivial extension to implement a one-to-many association: simply replace the fixed-size array with a dynamic container (for example a std::list)

image

Bi-directional 1:1 associations

If our association is bi-directional, then both classes need pointers. The problems come when you have to bind the objects together: which object gets built first?

image

If both classes need a pointer to the other in their constructors to work there is a cyclic dependency.

One solution is to provide a ‘binder’ function on each class that forms the association. In this example, the UI class has an additional member function, addStabiliser() that allows a CameraStabiliser object to be bound to it. The CameraStabiliser class has a complementary function.

image

At construction time, the CameraStabiliser and UI objects are constructed. Then the objects are bound together by calling the ‘bind’ functions. Notice, the programmer must ensure that the objects are bound together before they are used, otherwise you may end up dereferencing null pointers! Having to check for null pointers may seem a major drawback of this technique but it should be remembered that, sometimes, your design may actually require an unfulfilled association.  If that isn’t the case, using an assert in your code during development will highlight that you have failed to construct your system correctly.

A consequence of this approach is that the public interface of a class becomes ‘polluted’ with bind functions, which have nothing to do with the class’s functionality. This breaks the Single Responsibility Principle, which says an object should only have one reason to change. In this case, our classes have two reasons to change: their behaviour, which is part of their design; and their set of associations, which is a function of how they will be used in this particular project. These two aspects are orthogonal.  For example, the same class could be used in a very different way in another project, meaning it would most likely have a very different set of associations; even though its behaviour hasn’t changed.

An alternative approach is to create a free function that binds the two objects together.

image

Note, now both objects only have default constructors. The bind function forms the association between the two objects.

This approach has the benefit that it does not add any (non-behavioural) functions to the public interface of either class.

However, there is a problem with this code.

image

The bind function is not a member of either the UI or CameraStabiliser classes, so therefore cannot access their private data members (in this case, the association pointers)

Making the pointers public would allow this code to work but this exposes the pointers to clients and breaks encapsulation.

The solution is to make the bind function a friend function. A friend function is granted access to the private members of the class.

image

Notice the bind function must be made a friend of both the UI and CameraStabiliser classes.

The above is the general case for forming associations: a pointer plus a friend bind function. This will work for all associations – even the simplest case (1:1 unidirectional). For consistency of code this is the method I generally promote.

image

Reducing compile-time dependencies

Including one header file within another builds a dependency (coupling) between the two interfaces. Wherever possible we want to reduce the coupling between modules in our design.

image

In this case, including the class definition of class Sensor is unnecessary. You only need to include the class definition if:

  • You are going to allocate memory for an object
  • Inherit from an class
  • Call one of the class’s member functions.

Class Positioner does not instantiate a Sensor object; it merely has a pointer to a Sensor object. Since the compiler knows how much memory to allocate for a pointer we do not need to include the class definition of Sensor.

However, we must still declare that class Sensor is a valid type to satisfy the compiler. In this case we do so with a forward reference – actually just a pure declaration that class Sensor exists (somewhere).

image

Note: if we wish to call any of Sensor’s member functions we must include the class definition.

image

Summary

Adopting consistent idioms is the core of building maintainable code; making every construct a special case just makes code difficult to read, understand, extend and adapt.

In an object oriented design classes don’t just exist in isolation: they are inter-connected and their interactions are what provide the system’s behaviour. Understanding the need for, and implementation of, associations is a basic, fundamental skill for any C++ programmer.

 

If you’d like to know more about C++ programming – particularly for embedded and real-time applications – visit the Feabhas website. You may find the following of interest:

C++-501 – C++ for Embedded Developers

C++-502 – C++ for Real-Time Developers

AC++-501 – Advanced C++

AC++11-401 – Transitioning to C++11.

DP-403 – Design patterns for C++

On BashLite and Shellshock

November 19th, 2014

A number of people have been in touch with me about the fact that our Linux courses use an embedded target system that deploys BusyBox as standard and that there’s a “known exploit” doing the rounds called BashLite.SMB – this is obviously a cause for alarm!… Right?

WRONG!! Never one to shy away from defending my beloved Linux I wanted to make a quick public service announcement to say that this appears to be a fairly run-of-the-mill piece of malware riding on the coat tails of the significantly more dangerous ShellShock vulnerability which should be patched!

Busybox itself was never vulnerable to the Shellshock exploit due to it’s usage of an alternative shell – ash – which isn’t a bug-for-bug implementation of Bash.
BashLite is a backdoor opening, information stealing tool that can also be used as part of Command & Control based attacks and is typically the second prong of an attack that has already granted access to the system – either by ShellShock itself (you’re not running unpatched Bash on your device are you?) or by administrators and/or implementers deploying backdoored scanners to check their devices for ShellShock.

My advice is to keep devices off of the Internet during development, make sure they’re clean, keep your dev machines up-to-date with the latest patches, don’t ship devices that rely on components that have a history of bugs (and don’t expose said component via the web!), design and utilise an update strategy – preferably one that can be automated – and don’t trust everything you read on the internet!

If you’re really concerned about security and the types of attacks faced by embedded Linux users and how they work then I heartily recommend our new Secure Linux Programming course.

 

 

%d bloggers like this: