Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

C++ for resource-constrained systems

82 views
Skip to first unread message

bitrex

unread,
Nov 8, 2016, 1:34:53 PM11/8/16
to
I've read that contrary to popular belief, it's quite feasible to write
effective C++ code for small microprocessors without MMUs such as the
low-tier ARMs, and even AVR 8-bits with only say a couple kilobytes of
working memory.

That the code size for some constructs using say avr-g++ can actually
end up smaller than attempting to write something equivalent in straight
C, simply due to the more "expressive" syntax.

Clearly not all subsets of the language will be feasible to use on such
limited hardware, without a MMU dynamic memory allocation becomes much
more problematic, everything should be instantiated at execution (or at
least appropriate fixed-size buffers should be allocated), stuff like
unique_ptr and other allocation management features of C++11 and later
are certainly out, and the implementations I've seen of the STL for such
architectures are definitely not entirely C++11 compatible.

The performance hit of some types of template metaprogramming and
vtables of polymorphism is also a question.

My question is, what would you take from say C++11, and what would you
leave?

Jerry Stuckle

unread,
Nov 8, 2016, 2:04:47 PM11/8/16
to
On 11/8/2016 1:34 PM, bitrex wrote:
> I've read that contrary to popular belief, it's quite feasible to write
> effective C++ code for small microprocessors without MMUs such as the
> low-tier ARMs, and even AVR 8-bits with only say a couple kilobytes of
> working memory.
>
> That the code size for some constructs using say avr-g++ can actually
> end up smaller than attempting to write something equivalent in straight
> C, simply due to the more "expressive" syntax.
>
> Clearly not all subsets of the language will be feasible to use on such
> limited hardware, without a MMU dynamic memory allocation becomes much
> more problematic, everything should be instantiated at execution (or at
> least appropriate fixed-size buffers should be allocated), stuff like
> unique_ptr and other allocation management features of C++11 and later
> are certainly out, and the implementations I've seen of the STL for such
> architectures are definitely not entirely C++11 compatible.
>

Why do you need MMU dynamic memory allocation? I ran C++ quite well
under MS-DOS back in the late 80's and have used it on some embedded
systems since then. Just because you don't have an MMU doesn't mean you
can't dynamically allocate memory in the program. It's all in the
library code.

> The performance hit of some types of template metaprogramming and
> vtables of polymorphism is also a question.
>
> My question is, what would you take from say C++11, and what would you
> leave?

I wouldn't take anything out. But I wouldn't necessarily use everything
on any one project.

A couple of kb of memory causes other problems. When you get that
small, much of the programming is in assembler and/or a very limited
subset of C.

--
==================
Remove the "x" from my email address
Jerry Stuckle
jstu...@attglobal.net
==================

Alf P. Steinbach

unread,
Nov 8, 2016, 2:05:52 PM11/8/16
to
On 08.11.2016 19:34, bitrex wrote:
> I've read that contrary to popular belief, it's quite feasible to write
> effective C++ code for small microprocessors without MMUs such as the
> low-tier ARMs, and even AVR 8-bits with only say a couple kilobytes of
> working memory.
>
> That the code size for some constructs using say avr-g++ can actually
> end up smaller than attempting to write something equivalent in straight
> C, simply due to the more "expressive" syntax.
>
> Clearly not all subsets of the language will be feasible to use on such
> limited hardware, without a MMU dynamic memory allocation becomes much
> more problematic, everything should be instantiated at execution (or at
> least appropriate fixed-size buffers should be allocated), stuff like
> unique_ptr and other allocation management features of C++11 and later
> are certainly out,

That's not obvious to me. E.g. `unique_ptr` has zero overhead for most
uses. The question is whether the platforms have C++11 compilers.


> and the implementations I've seen of the STL for such
> architectures are definitely not entirely C++11 compatible.

Well then.


> The performance hit of some types of template metaprogramming and
> vtables of polymorphism is also a question.
>
> My question is, what would you take from say C++11, and what would you
> leave?

From Wikipedia's article on Embedded C++ (EC++, it's very out of
fashion now, but it's an example of doing what you suggest):

> Embedded C++ is a proper subset of C++. The following language
> features have been removed:
>
> Multiple inheritance
> Virtual base classes
> Run-time type information (typeid)
> New style casts (static_cast, dynamic_cast, reinterpret_cast and const_cast)
> The mutable storage class specifier
> Namespaces
> Exceptions
> Templates

I think the points after the first three, are just dumb from a modern
perspective: the new style casts provide safety at no run time cost
(except dynamic_cast which goes with RTTI), ditto for the `mutable`
keyword, ditto for namespaces, ditto for templates, and I think it was
Nokia who tried the idea of C++ without exceptions, it was pretty messy.
So the list revised with (1) the criterion that there must be some
reason, some advantage, for a removal, and (2) considering the Nokia
(whatever) experience about exceptions, appears to be

• Multiple inheritance
• Virtual base classes
• (C++11) Threading.
• (C++11) Support for garbage collection.

My last point here may be arguable. After all, Java started as a
language for controlling television sets, as I recall. But I think in
general in the embedded world it must be nice to have predictability.

Cheers & hth.,

- Alf

Alf P. Steinbach

unread,
Nov 8, 2016, 2:07:43 PM11/8/16
to
On 08.11.2016 20:03, Alf P. Steinbach wrote:
> So the list revised with (1) the criterion that there must be some
> reason, some advantage, for a removal, and (2) considering the Nokia
> (whatever) experience about exceptions, appears to be
>
> • Multiple inheritance
> • Virtual base classes
• RTTI!
> • (C++11) Threading.
> • (C++11) Support for garbage collection.
>
> My last point here may be arguable. After all, Java started as a
> language for controlling television sets, as I recall. But I think in
> general in the embedded world it must be nice to have predictability.

Sorry, RTTI somehow disappeared from the list. Grumble.


Cheers!,

- Alf


bitrex

unread,
Nov 8, 2016, 2:16:03 PM11/8/16
to
On 11/08/2016 02:03 PM, Alf P. Steinbach wrote:

> • Multiple inheritance
> • Virtual base classes
> • (C++11) Threading.
> • (C++11) Support for garbage collection.
>
> My last point here may be arguable. After all, Java started as a
> language for controlling television sets, as I recall. But I think in
> general in the embedded world it must be nice to have predictability.
>
> Cheers & hth.,
>
> - Alf
>

What's the main issue with virtual base classes? I know there is
overhead associated with the vtable and the methods can't be inlined,
but aside from that it doesn't seem overly onerous in the grand scheme
of things.

So like, just don't use polymorphism in time-critical areas?

Scott Lurndal

unread,
Nov 8, 2016, 2:30:07 PM11/8/16
to
bitrex <bit...@de.lete.earthlink.net> writes:

>
>My question is, what would you take from say C++11, and what would you
>leave?

Use the language as of C++ 2.1 (before exceptions, STL and templates). Entire
operating systems have been written in that dialog (effectively C with classes).

Öö Tiib

unread,
Nov 8, 2016, 3:32:23 PM11/8/16
to
On Tuesday, 8 November 2016 21:16:03 UTC+2, bitrex wrote:
> On 11/08/2016 02:03 PM, Alf P. Steinbach wrote:
>
> > • Multiple inheritance
> > • Virtual base classes
> > • (C++11) Threading.
> > • (C++11) Support for garbage collection.
> >
> > My last point here may be arguable. After all, Java started as a
> > language for controlling television sets, as I recall. But I think in
> > general in the embedded world it must be nice to have predictability.
> >
> > Cheers & hth.,
> >
> > - Alf
> >
>
> What's the main issue with virtual base classes?

The virtual base classes are for to solve design error named "diamond inheritance" with odd and inefficient hack. It must indeed be banned
together with that diamond inheritance from any sane code.

> I know there is
> overhead associated with the vtable and the methods can't be inlined,
> but aside from that it doesn't seem overly onerous in the grand scheme
> of things.

It seems that you mix up two terms "virtual functions" and "virtual
base classes".

>
> So like, just don't use polymorphism in time-critical areas?

Virtual functions are usually OK in profile. Meaningful virtual call can
be more efficient than the alternatives to it. For example lengthy
switch-case on some "type" member can be slower. For other example usage
of function pointers in objects can take more memory (and so cause more
cache misses).

David Brown

unread,
Nov 8, 2016, 3:54:00 PM11/8/16
to
On 08/11/16 20:03, Alf P. Steinbach wrote:
> On 08.11.2016 19:34, bitrex wrote:
>> I've read that contrary to popular belief, it's quite feasible to write
>> effective C++ code for small microprocessors without MMUs such as the
>> low-tier ARMs, and even AVR 8-bits with only say a couple kilobytes of
>> working memory.
>>
>> That the code size for some constructs using say avr-g++ can actually
>> end up smaller than attempting to write something equivalent in straight
>> C, simply due to the more "expressive" syntax.
>>
>> Clearly not all subsets of the language will be feasible to use on such
>> limited hardware, without a MMU dynamic memory allocation becomes much
>> more problematic, everything should be instantiated at execution (or at
>> least appropriate fixed-size buffers should be allocated), stuff like
>> unique_ptr and other allocation management features of C++11 and later
>> are certainly out,
>
> That's not obvious to me. E.g. `unique_ptr` has zero overhead for most
> uses.

There are a number of C++ features (such as unique_ptr) that are zero
overhead. There are many others that use dynamic memory behind the
scenes (such as shared_ptr), and it is not always easy to know which are
which.

> The question is whether the platforms have C++11 compilers.

Yes, these platforms have C++11 compilers. The targets mentioned were
ARM microcontrollers and AVRs - gcc is the standard compiler for both of
these. However, the C++ library may not be complete - last I heard, the
avr library did not support exceptions or RTTI.


>
>> and the implementations I've seen of the STL for such
>> architectures are definitely not entirely C++11 compatible.
>
> Well then.
>
>
>> The performance hit of some types of template metaprogramming and
>> vtables of polymorphism is also a question.
>>
>> My question is, what would you take from say C++11, and what would you
>> leave?
>
> From Wikipedia's article on Embedded C++ (EC++, it's very out of fashion
> now, but it's an example of doing what you suggest):
>
>> Embedded C++ is a proper subset of C++. The following language
>> features have been removed:
>>
>> Multiple inheritance
>> Virtual base classes
>> Run-time type information (typeid)
>> New style casts (static_cast, dynamic_cast, reinterpret_cast and
>> const_cast)
>> The mutable storage class specifier
>> Namespaces
>> Exceptions
>> Templates

EC++ was a total failure from its first inception - it was never /in/
fashion. It made it just as hard to avoid accidentally incurring costs
(such as from dynamic memory that you did not realise you were using),
while disallowing many useful features that are either entirely free
(like namespaces) or which can save you space and time if used correctly
(like templates).

Vir Campestris

unread,
Nov 8, 2016, 3:57:53 PM11/8/16
to
On 08/11/2016 20:32, Öö Tiib wrote:
> The virtual base classes are for to solve design error named "diamond inheritance" with odd and inefficient hack. It must indeed be banned
> together with that diamond inheritance from any sane code.

I've used it exactly once. The design error is in the specification for
DVDs - some fields can be any one of three types. Others are restricted
to exactly two - but it isn't always the same 2.

Andy

Vir Campestris

unread,
Nov 8, 2016, 3:59:01 PM11/8/16
to
On 08/11/2016 20:53, David Brown wrote:
> However, the C++ library may not be complete - last I heard, the avr
> library did not support exceptions or RTTI.

This may be more of a problem than anything else. The C++ RTL is
significantly bigger than C. (I've just watched my smart pointer bug
fixes be replaced by a bit of C ...)

Andy

David Brown

unread,
Nov 8, 2016, 3:59:24 PM11/8/16
to
On 08/11/16 21:32, Öö Tiib wrote:
> On Tuesday, 8 November 2016 21:16:03 UTC+2, bitrex wrote:
<snip>
>
>> I know there is
>> overhead associated with the vtable and the methods can't be inlined,
>> but aside from that it doesn't seem overly onerous in the grand scheme
>> of things.
>
> It seems that you mix up two terms "virtual functions" and "virtual
> base classes".
>

Virtual methods can be inlined (or at least de-virtualised) if the
compiler knows the real type of an object at compile time. If you have
created an object of the descendent class and call its methods without
first converting it to a pointer to its base class, then the compiler
knows exactly which method to call and can inline it or de-virtualise
it. The only overhead is then the hidden vtable entry in the class object.

>>
>> So like, just don't use polymorphism in time-critical areas?
>
> Virtual functions are usually OK in profile. Meaningful virtual call can
> be more efficient than the alternatives to it. For example lengthy
> switch-case on some "type" member can be slower. For other example usage
> of function pointers in objects can take more memory (and so cause more
> cache misses).
>

This can depend on the code in question, and also the target in
question. From the examples given, ARM microcontrollers are quite
efficient at calling virtual functions, but for an AVR there would be
significant overhead.

David Brown

unread,
Nov 8, 2016, 4:02:55 PM11/8/16
to
The C++ RTL is not big if you disable exceptions and RTTI (as you need
to anyway, for the AVR). You only pay for the features you use. (But
it is easy to use dynamic memory without intending to. It is easy in C,
and even easier in C++.)


Wouter van Ooijen

unread,
Nov 8, 2016, 5:47:10 PM11/8/16
to
Op 08-Nov-16 om 7:34 PM schreef bitrex:
> I've read that contrary to popular belief, it's quite feasible to write
> effective C++ code for small microprocessors without MMUs such as the
> low-tier ARMs, and even AVR 8-bits with only say a couple kilobytes of
> working memory.

Actually there are quite a few persons that actively promote using (a
suitable part of) C++ on small microcontroller.

The main problem with AVRs is that they don't have a unified address
space, so you can't have a pointer that can point to ROM or RAM. This
makes consexpr much less effecitive.

> That the code size for some constructs using say avr-g++ can actually
> end up smaller than attempting to write something equivalent in straight
> C, simply due to the more "expressive" syntax.

Templates are your friend (if used well). So is whole-program
optimization. And constexpr!

> Clearly not all subsets of the language will be feasible to use on such
> limited hardware, without a MMU dynamic memory allocation becomes much
> more problematic

Why? You can have a hep in 2k RAM if you want. The main reasons the heap
is mostly not used in small systems are:
- unpredictable real-time performance
- fragmentation
- not knowing upfront whether everything will fit

>, everything should be instantiated at execution (or at
> least appropriate fixed-size buffers should be allocated), stuff like
> unique_ptr and other allocation management features of C++11 and later
> are certainly out, and the implementations I've seen of the STL for such
> architectures are definitely not entirely C++11 compatible.
>
> The performance hit of some types of template metaprogramming and
> vtables of polymorphism is also a question.

The performance penalty of template metaprogramming occurs at
compile-time, so that is a big win!

V-tables and run-time polymorphism are a great tool *if you need it*. If
you can live with compile-time polymorphism templates can deliver that
at zero run-time cost.

> My question is, what would you take from say C++11, and what would you
> leave?

Give me C++17 or better 20 (concepts, finally?).

Leaving something out of the language is not a good idea. That would
split the language community and introduce backwards incompatibility.

What I do like is a library that doesn't *force* me to use
- exceptions
- heap
- RTTI
- floating point
when I don't need it. So I'd like to see fixed-maximum-size containers
and string.

And I'd like to see toolchain flags that ensure that those features are
not used (some are already available). And as for toolchains: I'd like
to have a limited stack size, and warnings when the compiler can't
determine the stack size. And I hate ctors, so I'd like an option to
make those a warning too. (I can detect them at link time, but that
amkes it difficult to find back the offending source line).

If you want this explained in more detail, check my Meeting C++ talk:
https://meetingcpp.com/index.php/tv15/items/17.html

Wouter "Objects? No Thanks" van Ooijen

Öö Tiib

unread,
Nov 8, 2016, 6:57:07 PM11/8/16
to
Hmm. I can not see how diamond inheritance helps with that situation.

David Brown

unread,
Nov 9, 2016, 3:58:24 AM11/9/16
to
On 08/11/16 23:47, Wouter van Ooijen wrote:
> Op 08-Nov-16 om 7:34 PM schreef bitrex:
>> I've read that contrary to popular belief, it's quite feasible to write
>> effective C++ code for small microprocessors without MMUs such as the
>> low-tier ARMs, and even AVR 8-bits with only say a couple kilobytes of
>> working memory.
>
> Actually there are quite a few persons that actively promote using (a
> suitable part of) C++ on small microcontroller.
>
> The main problem with AVRs is that they don't have a unified address
> space, so you can't have a pointer that can point to ROM or RAM. This
> makes consexpr much less effecitive.

It is more of a problem for const than constexpr. constexpr code can be
figured out at compile time (assuming all the parameters are known at
compile time), and the AVR will have no problem dealing with the
results. The challenge for the AVR is when you have const data that you
would like to be held in flash (since the chips have limited ram space)
- it takes different code to read the data from flash than it does to
read it from ram.

A second key problem on the AVR is that it has very poor pointer
support, and poor "stack + offset" addressing. This quickly means that
a lot of neat, structured C++ code with pointers, references, etc.,
becomes quite inefficient compared to code using static variables. This
applies to C as well, but in C++ you regularly have a "*this" pointer as
well.

And libstdc++ is not implemented in avr-gcc as yet. This means no
standard C++ classes, no new and delete, no exceptions. But you still
get strong typing, templates, namespaces, constexpr, classes, etc. (I
wonder if lambdas work?)

>
>> That the code size for some constructs using say avr-g++ can actually
>> end up smaller than attempting to write something equivalent in straight
>> C, simply due to the more "expressive" syntax.
>
> Templates are your friend (if used well). So is whole-program
> optimization. And constexpr!

Or LTO, as it is now - "-fwhole-program" is out of fashion. LTO has its
challenges with debugging, however.

>
>> Clearly not all subsets of the language will be feasible to use on such
>> limited hardware, without a MMU dynamic memory allocation becomes much
>> more problematic
>
> Why? You can have a hep in 2k RAM if you want. The main reasons the heap
> is mostly not used in small systems are:
> - unpredictable real-time performance
> - fragmentation
> - not knowing upfront whether everything will fit

Agreed. I don't see why an MMU would be an issue here. An MMU can be
useful to reduce fragmentation on a larger scale (such as 4K pages), but
it is hardly helpful if you have 4K ram in total!

>
>> , everything should be instantiated at execution (or at
>> least appropriate fixed-size buffers should be allocated), stuff like
>> unique_ptr and other allocation management features of C++11 and later
>> are certainly out, and the implementations I've seen of the STL for such
>> architectures are definitely not entirely C++11 compatible.
>>
>> The performance hit of some types of template metaprogramming and
>> vtables of polymorphism is also a question.
>
> The performance penalty of template metaprogramming occurs at
> compile-time, so that is a big win!

People often mistakenly believe that templates mean code bloat. When
used correctly, and with good tool support, templates can reduce code size.

>
> V-tables and run-time polymorphism are a great tool *if you need it*. If
> you can live with compile-time polymorphism templates can deliver that
> at zero run-time cost.
>
>> My question is, what would you take from say C++11, and what would you
>> leave?
>
> Give me C++17 or better 20 (concepts, finally?).
>
> Leaving something out of the language is not a good idea. That would
> split the language community and introduce backwards incompatibility.
>
> What I do like is a library that doesn't *force* me to use
> - exceptions
> - heap
> - RTTI
> - floating point
> when I don't need it. So I'd like to see fixed-maximum-size containers
> and string.

Agreed.

>
> And I'd like to see toolchain flags that ensure that those features are
> not used (some are already available). And as for toolchains: I'd like
> to have a limited stack size, and warnings when the compiler can't
> determine the stack size.

Agreed. The more warnings you can get at compile time, the better.

> And I hate ctors, so I'd like an option to
> make those a warning too. (I can detect them at link time, but that
> amkes it difficult to find back the offending source line).

That one I don't get. You hate constructors? They are pretty essential
to the whole concept of classes, and to RAII in particular.

The only thing that is a mess is the global constructor order problem.
It would be nice to have a /real/ solution to that one. Ideally, if a
global/static object's constructor refers to another global/static
object, then the referred-to object should be ordered earlier in the
constructor list. Then it should all be safe.

Ian Collins

unread,
Nov 9, 2016, 4:04:06 AM11/9/16
to
On 11/ 9/16 07:34 AM, bitrex wrote:
> I've read that contrary to popular belief, it's quite feasible to write
> effective C++ code for small microprocessors without MMUs such as the
> low-tier ARMs, and even AVR 8-bits with only say a couple kilobytes of
> working memory.

Yes, C++ (or an appropriate subset) isn't uncommon on small systems.
I've worked a couple of C++ projects on small ARMs.

> That the code size for some constructs using say avr-g++ can actually
> end up smaller than attempting to write something equivalent in straight
> C, simply due to the more "expressive" syntax.
>
> Clearly not all subsets of the language will be feasible to use on such
> limited hardware, without a MMU dynamic memory allocation becomes much
> more problematic, everything should be instantiated at execution (or at
> least appropriate fixed-size buffers should be allocated), stuff like
> unique_ptr and other allocation management features of C++11 and later
> are certainly out, and the implementations I've seen of the STL for such
> architectures are definitely not entirely C++11 compatible.

Most applications on memory constrained system shun dynamic allocation.

> The performance hit of some types of template metaprogramming and
> vtables of polymorphism is also a question.

The former is entirely a compile time overhead, virtual functions are
seldom a problem on modern CPUs.

> My question is, what would you take from say C++11, and what would you
> leave?

The biggest problem I see is the lack of direct support for small
systems in the standard. It would be nice if there were a subset of
standard library headers that were guaranteed not to use constructs
requiring dynamic memory or exceptions for example. <array> and
<algorithm> are obvious contenders.

--
Ian

Richard

unread,
Nov 9, 2016, 1:54:32 PM11/9/16
to
[Please do not mail me a copy of your followup]

Ian Collins <ian-...@hotmail.com> spake the secret code
<e8g73t...@mid.individual.net> thusly:

>The biggest problem I see is the lack of direct support for small
>systems in the standard. It would be nice if there were a subset of
>standard library headers that were guaranteed not to use constructs
>requiring dynamic memory or exceptions for example. <array> and
><algorithm> are obvious contenders.

You might see some useful work coming from the "gaming and real-time
programming" working group in the standards committee. In
particular, you might want to look at Electronic Arts STL.
--
"The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline>
The Terminals Wiki <http://terminals-wiki.org>
The Computer Graphics Museum <http://computergraphicsmuseum.org>
Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com>

Wouter van Ooijen

unread,
Nov 10, 2016, 2:14:41 AM11/10/16
to
Op 09-Nov-16 om 9:58 AM schreef David Brown:
> On 08/11/16 23:47, Wouter van Ooijen wrote:
>> Op 08-Nov-16 om 7:34 PM schreef bitrex:
>>> I've read that contrary to popular belief, it's quite feasible to write
>>> effective C++ code for small microprocessors without MMUs such as the
>>> low-tier ARMs, and even AVR 8-bits with only say a couple kilobytes of
>>> working memory.
>>
>> Actually there are quite a few persons that actively promote using (a
>> suitable part of) C++ on small microcontroller.
>>
>> The main problem with AVRs is that they don't have a unified address
>> space, so you can't have a pointer that can point to ROM or RAM. This
>> makes consexpr much less effecitive.
>
> It is more of a problem for const than constexpr.

You are technically correct (although in C++14 constexpr implies const),
and constexpr has widened the opportunity for const tremendously.

> A second key problem on the AVR is that it has very poor pointer
> support, and poor "stack + offset" addressing. This quickly means that
> a lot of neat, structured C++ code with pointers, references, etc.,
> becomes quite inefficient compared to code using static variables. This
> applies to C as well, but in C++ you regularly have a "*this" pointer as
> well.

True, but not a problem for me. My preferred small-system coding style
avoids indirection.

> And libstdc++ is not implemented in avr-gcc as yet. This means no
> standard C++ classes, no new and delete, no exceptions. But you still
> get strong typing, templates, namespaces, constexpr, classes, etc. (I
> wonder if lambdas work?)

I'll have to check. I use AVR only to check whether what I do is
portable to 8 bit.

My guess is that std::function doesn't work, but passing a lambda and
using it directly will work.

> Or LTO, as it is now - "-fwhole-program" is out of fashion. LTO has its
> challenges with debugging, however.

Samll real-time systems are difficult to debug anyway.

> People often mistakenly believe that templates mean code bloat. When
> used correctly, and with good tool support, templates can reduce code size.

spread the word!

>> And I hate ctors, so I'd like an option to
>> make those a warning too. (I can detect them at link time, but that
>> amkes it difficult to find back the offending source line).
>
> That one I don't get. You hate constructors? They are pretty essential
> to the whole concept of classes, and to RAII in particular.
>
> The only thing that is a mess is the global constructor order problem.
> It would be nice to have a /real/ solution to that one. Ideally, if a
> global/static object's constructor refers to another global/static
> object, then the referred-to object should be ordered earlier in the
> constructor list. Then it should all be safe.

I wasn't clear, I meant global ctors.

David Brown

unread,
Nov 10, 2016, 5:00:11 AM11/10/16
to
On 10/11/16 08:14, Wouter van Ooijen wrote:
> Op 09-Nov-16 om 9:58 AM schreef David Brown:
>> On 08/11/16 23:47, Wouter van Ooijen wrote:
>>> Op 08-Nov-16 om 7:34 PM schreef bitrex:
>>>> I've read that contrary to popular belief, it's quite feasible to write
>>>> effective C++ code for small microprocessors without MMUs such as the
>>>> low-tier ARMs, and even AVR 8-bits with only say a couple kilobytes of
>>>> working memory.
>>>
>>> Actually there are quite a few persons that actively promote using (a
>>> suitable part of) C++ on small microcontroller.
>>>
>>> The main problem with AVRs is that they don't have a unified address
>>> space, so you can't have a pointer that can point to ROM or RAM. This
>>> makes consexpr much less effecitive.
>>
>> It is more of a problem for const than constexpr.
>
> You are technically correct (although in C++14 constexpr implies const),
> and constexpr has widened the opportunity for const tremendously.

constexpr implies const in many cases (though in C++14, non-static
constexpr member functions are no longer implicitly const). But there
are many cases of const objects that are not constexpr.

>
>> A second key problem on the AVR is that it has very poor pointer
>> support, and poor "stack + offset" addressing. This quickly means that
>> a lot of neat, structured C++ code with pointers, references, etc.,
>> becomes quite inefficient compared to code using static variables. This
>> applies to C as well, but in C++ you regularly have a "*this" pointer as
>> well.
>
> True, but not a problem for me. My preferred small-system coding style
> avoids indirection.

Fair enough. Certainly when programming on the AVR (something I haven't
done much for quite a while, and never in C++) I minimise my pointers.
On an ARM, however, pointers are often more efficient than direct
addressing.

It is just something to be aware of if you are looking for the most
efficient code.

>
>> And libstdc++ is not implemented in avr-gcc as yet. This means no
>> standard C++ classes, no new and delete, no exceptions. But you still
>> get strong typing, templates, namespaces, constexpr, classes, etc. (I
>> wonder if lambdas work?)
>
> I'll have to check. I use AVR only to check whether what I do is
> portable to 8 bit.
>
> My guess is that std::function doesn't work, but passing a lambda and
> using it directly will work.
>
>> Or LTO, as it is now - "-fwhole-program" is out of fashion. LTO has its
>> challenges with debugging, however.
>
> Samll real-time systems are difficult to debug anyway.

If this job were easy, anyone could do it!

>
>> People often mistakenly believe that templates mean code bloat. When
>> used correctly, and with good tool support, templates can reduce code
>> size.
>
> spread the word!
>
>>> And I hate ctors, so I'd like an option to
>>> make those a warning too. (I can detect them at link time, but that
>>> amkes it difficult to find back the offending source line).
>>
>> That one I don't get. You hate constructors? They are pretty essential
>> to the whole concept of classes, and to RAII in particular.
>>
>> The only thing that is a mess is the global constructor order problem.
>> It would be nice to have a /real/ solution to that one. Ideally, if a
>> global/static object's constructor refers to another global/static
>> object, then the referred-to object should be ordered earlier in the
>> constructor list. Then it should all be safe.
>
> I wasn't clear, I meant global ctors.
>

OK - then I (mostly) agree with you. Global constructors can be nice,
but the ordering problem is a pain. gcc's init_priority __attribute__
can help.



0 new messages