f



How to avoid malloc with encapsulation

I know encapsulation tecnique is a Good Thing in coding. Encapsulation 
means writing write well separated modules, similar to classes in OO 
languages.

Even in C, that isn't OO language, is possible to reach encapsulation by 
using a very simple ad effective trick: the instance of a "class" (C 
structure) is a pointer to the struct that isn't defined in .h (only 
typedef), but in .c.  For example, see here [1].

IMHO it's a very good approach, however it's difficult to implement in 
embedded systems where you lack the presence of malloc (and you don't 
like to use it for many many reasons).

The constructor/init/create function of the class/struct must allocate 
the space needed for the instance, but it cannot use a static allocation 
method (it doesn't know how many instances will be requested).

One solution is to abandon encapsulation and expose the internal 
definition of struct in the header file. In this way, the user (of the 
class) can allocate directly the instance, by defining a variable.

Another solution is to implement a minimalistic malloc inside the class 
source, maybe a simple memory pool where the number of elements are 
defined at compile time.

Do you have better solutions?



[1] https://alastairs-place.net/blog/2013/06/03/encapsulation-in-c/
0
pozz
12/21/2016 11:38:02 AM
comp.arch.embedded 20047 articles. 1 followers. Post Follow

15 Replies
814 Views

Similar Articles

[PageSpeed] 53

Il giorno mercoled=C3=AC 21 dicembre 2016 12:38:04 UTC+1, pozz ha scritto:
> I know encapsulation tecnique is a Good Thing in coding. Encapsulation=20
> means writing write well separated modules, similar to classes in OO=20
> languages.
>=20
> Even in C, that isn't OO language, is possible to reach encapsulation by=
=20
> using a very simple ad effective trick: the instance of a "class" (C=20
> structure) is a pointer to the struct that isn't defined in .h (only=20
> typedef), but in .c.  For example, see here [1].
>=20
> IMHO it's a very good approach, however it's difficult to implement in=20
> embedded systems where you lack the presence of malloc (and you don't=20
> like to use it for many many reasons).
>=20
> The constructor/init/create function of the class/struct must allocate=20
> the space needed for the instance, but it cannot use a static allocation=
=20
> method (it doesn't know how many instances will be requested).
>=20
> One solution is to abandon encapsulation and expose the internal=20
> definition of struct in the header file. In this way, the user (of the=20
> class) can allocate directly the instance, by defining a variable.
>=20
> Another solution is to implement a minimalistic malloc inside the class=
=20
> source, maybe a simple memory pool where the number of elements are=20
> defined at compile time.
>=20
> Do you have better solutions?

smart use of the preprocessor.

Bye Jack
0
Jack
12/21/2016 11:56:37 AM
keskiviikko 21. joulukuuta 2016 13.38.04 UTC+2 pozz kirjoitti:
> I know encapsulation tecnique is a Good Thing in coding. Encapsulation 
> means writing write well separated modules, similar to classes in OO 
> languages.
> 
> Even in C, that isn't OO language, is possible to reach encapsulation by 
> using a very simple ad effective trick: the instance of a "class" (C 
> structure) is a pointer to the struct that isn't defined in .h (only 
> typedef), but in .c.  For example, see here [1].
> 
> IMHO it's a very good approach, however it's difficult to implement in 
> embedded systems where you lack the presence of malloc (and you don't 
> like to use it for many many reasons).
> 
> The constructor/init/create function of the class/struct must allocate 
> the space needed for the instance, but it cannot use a static allocation 
> method (it doesn't know how many instances will be requested).
> 
> One solution is to abandon encapsulation and expose the internal 
> definition of struct in the header file. In this way, the user (of the 
> class) can allocate directly the instance, by defining a variable.
> 
> Another solution is to implement a minimalistic malloc inside the class 
> source, maybe a simple memory pool where the number of elements are 
> defined at compile time.
> 
> Do you have better solutions?
> 
> 
> 
> [1] https://alastairs-place.net/blog/2013/06/03/encapsulation-in-c/

Typically using malloc is ok during system initialization time. An alternative to malloc are resource pools. Just allocate the needed resources when the system is booting up. 

Br,
Kalvin
0
kalvin
12/21/2016 12:23:25 PM
On Wed, 21 Dec 2016 12:38:02 +0100, pozz <pozzugno@gmail.com> wrote:

>I know encapsulation tecnique is a Good Thing in coding. Encapsulation 
>means writing write well separated modules, similar to classes in OO 
>languages.
>
>Even in C, that isn't OO language, is possible to reach encapsulation by 
>using a very simple ad effective trick: the instance of a "class" (C 
>structure) is a pointer to the struct that isn't defined in .h (only 
>typedef), but in .c.  For example, see here [1].
>
>IMHO it's a very good approach, however it's difficult to implement in 
>embedded systems where you lack the presence of malloc (and you don't 
>like to use it for many many reasons).
>
>The constructor/init/create function of the class/struct must allocate 
>the space needed for the instance, but it cannot use a static allocation 
>method (it doesn't know how many instances will be requested).

The question is, when do you know, how many structs/objects are
actually needed. If you can determine this at startup e.g. by checking
existing hardware or reading a configuration file, thus you know how
much is needed and allocate it from the stack or very primitive malloc
(used once). 

The problem gets harder, if you after five years of running, some
additional allocations are needed. Even in this case, check if you can
do the allocation from the stack.

Most processors these days have quite usable stack related addressing
modes, thus not too badly cutting the performance.

0
upsidedown
12/21/2016 1:57:09 PM
Op 21-Dec-16 om 12:38 PM schreef pozz:
> I know encapsulation tecnique is a Good Thing in coding. Encapsulation
> means writing write well separated modules, similar to classes in OO
> languages.
>
> Even in C, that isn't OO language, is possible to reach encapsulation by
> using a very simple ad effective trick: the instance of a "class" (C
> structure) is a pointer to the struct that isn't defined in .h (only
> typedef), but in .c.  For example, see here [1].
>
> IMHO it's a very good approach, however it's difficult to implement in
> embedded systems where you lack the presence of malloc (and you don't
> like to use it for many many reasons).
>
> The constructor/init/create function of the class/struct must allocate
> the space needed for the instance, but it cannot use a static allocation
> method (it doesn't know how many instances will be requested).
>
> One solution is to abandon encapsulation and expose the internal
> definition of struct in the header file. In this way, the user (of the
> class) can allocate directly the instance, by defining a variable.
>
> Another solution is to implement a minimalistic malloc inside the class
> source, maybe a simple memory pool where the number of elements are
> defined at compile time.
>
> Do you have better solutions?

Use C++.

(Just as with C, this means use *as suitable subset* of C++.)

Wouter "Objects? No Thanks!" van Ooijen

0
Wouter
12/21/2016 5:06:36 PM
On 12/21/2016 4:38 AM, pozz wrote:
> I know encapsulation tecnique is a Good Thing in coding. Encapsulation means
> writing write well separated modules, similar to classes in OO languages.
>
> Even in C, that isn't OO language, is possible to reach encapsulation by using
> a very simple ad effective trick: the instance of a "class" (C structure) is a
> pointer to the struct that isn't defined in .h (only typedef), but in .c.  For
> example, see here [1].
>
> IMHO it's a very good approach, however it's difficult to implement in embedded
> systems where you lack the presence of malloc (and you don't like to use it for
> many many reasons).
>
> The constructor/init/create function of the class/struct must allocate the
> space needed for the instance, but it cannot use a static allocation method (it
> doesn't know how many instances will be requested).
>
> One solution is to abandon encapsulation and expose the internal definition of
> struct in the header file. In this way, the user (of the class) can allocate
> directly the instance, by defining a variable.
>
> Another solution is to implement a minimalistic malloc inside the class source,
> maybe a simple memory pool where the number of elements are defined at compile
> time.
>
> Do you have better solutions?

What's the problem with malloc()?

You are going to instantiate some object(s) of some class(es).

If they are ALL persistent, then use malloc to create them on *the* heap,
as/when needed, and then never call free().  This is no different than
static instances scattered around memory -- except that they're all in one
place.

The issue comes when you want to create and then *destroy* individual instances
(in any order imaginable) and are fearful of heap fragmentation (assuming you
don't have more elaborate memory management mechanisms).

As your constructor knows the size/shape of the object, let its constructor
allocate a "buffer" from a pool created for that class.  Define the size
of the pool (i.e., number of such class objects that can be instantiated)
either at compile time *or* with a member function/variable that allocates
the "pool" from The Heap (the *pool* will never be deleted so The Heap
never experiences fragmentation as a result of that).

A cleaner approach is to write a generic malloc that can operate on any
of several arenas.  So, when creating the pool for ClassX, you use
The System Heap as the arena.  Likewise, when creating the pool for
ClassY, ClassZ, etc.

Having created each of these (at system initialization time -- which allows
you to defer making a decision regarding number of such objects of each class
that might be required in this instance of the application), you now use the
appropriate "class heap" (pool) as the arena when malloc()-ing buffers for
each object instance of that type.

Make arenas "trivial" and you can create "local instances" on the stack,
etc.

As the developer, if you happen to *know* that ClassX and ClassZ happen to
require the same amount of memory to instantiate, then you could instead create
a single heap (pool) from which you allocate *either* ClassX *or* ClassZ
objects.  This gives you some wiggle room if you underestimate the number of
ClassX objects but overestimate the number of ClassZ objects.

At *some* point, you have to have a real numeric value for the number of
X, Y and Z objects that your application requires.  If you want total
flexibility, then you need to manage them from a single heap.  If you
are fearful of fragmentation, then consider:
- making all objects the same size (padding as necessary)
- dynamically managing the objects with an extra level of
   indirection and letting a garbage collector shuffle them
   around in physical memory as *it* determines to be necessary
   (i.e., so it can "repack" the heap and move objects around
   to coalesce all free fragments into a single, large free-space)

E.g., I access each object through a "handle" so I don't care where
(in virtual memory) it resides -- or even on which *node* it may
currently exist.  This lets the *code* move it around as the code
sees fit -- instead of requiring me to keep track of where it
*should* be located.

Of course, all of these approaches have associated costs.  There are
no free lunches.
0
Don
12/21/2016 6:00:12 PM
On Wed, 21 Dec 2016 12:38:02 +0100, pozz wrote:

> I know encapsulation tecnique is a Good Thing in coding. Encapsulation
> means writing write well separated modules, similar to classes in OO
> languages.
> 
> Even in C, that isn't OO language, is possible to reach encapsulation by
> using a very simple ad effective trick: the instance of a "class" (C
> structure) is a pointer to the struct that isn't defined in .h (only
> typedef), but in .c.  For example, see here [1].
> 
> IMHO it's a very good approach, however it's difficult to implement in
> embedded systems where you lack the presence of malloc (and you don't
> like to use it for many many reasons).
> 
> The constructor/init/create function of the class/struct must allocate
> the space needed for the instance, but it cannot use a static allocation
> method (it doesn't know how many instances will be requested).
> 
> One solution is to abandon encapsulation and expose the internal
> definition of struct in the header file. In this way, the user (of the
> class) can allocate directly the instance, by defining a variable.
> 
> Another solution is to implement a minimalistic malloc inside the class
> source, maybe a simple memory pool where the number of elements are
> defined at compile time.
> 
> Do you have better solutions?
> 
> 
> 
> [1] https://alastairs-place.net/blog/2013/06/03/encapsulation-in-c/

Yes, that's a good way to do encapsulation.  I'd say just use C++ and 
don't use 'new', but the last time I tried using C++ on a processor with 
8k of memory, I discovered that there's a ton of code that gets pulled 
in.  Someone with a deeper understanding of newlib may have been able to 
stub all that off, but not I.

I can think of three approaches right off:

1: Statically allocate everything in the .c files, hard-coded.

This is easy enough if the 'objects' are directly connected to hardware 
entities like UARTs, and you're not reusing code across processors much.

2: Statically allocate everything in the .c files, from "config.h"

This is really 1a, but it lets you re-use your code, with a different 
"config.h" for each project.

3: Rewrite malloc and free.

Malloc just allocates blocks out of some free storage, and free calls 
assert (or does nothing, or pops a fault, or whatever).  Better yet, if 
you can make the linker do it, don't link in free at all.  You can't do 
this in C++ that I know of (at least with gnu C++ and newlib -- "delete" 
is too heavily embedded in the language), but in C you only pull in 
"free" if you explicitly use it.  Then if someone down the road tries to 
use "free" the linker will whack them upside the head.

-- 
Tim Wescott
Control systems, embedded software and circuit design
I'm looking for work!  See my website if you're interested
http://www.wescottdesign.com
0
Tim
12/21/2016 6:18:27 PM
On Wed, 21 Dec 2016 04:23:25 -0800, kalvin.news wrote:

> keskiviikko 21. joulukuuta 2016 13.38.04 UTC+2 pozz kirjoitti:
>> I know encapsulation tecnique is a Good Thing in coding. Encapsulation
>> means writing write well separated modules, similar to classes in OO
>> languages.
>> 
>> Even in C, that isn't OO language, is possible to reach encapsulation
>> by using a very simple ad effective trick: the instance of a "class" (C
>> structure) is a pointer to the struct that isn't defined in .h (only
>> typedef), but in .c.  For example, see here [1].
>> 
>> IMHO it's a very good approach, however it's difficult to implement in
>> embedded systems where you lack the presence of malloc (and you don't
>> like to use it for many many reasons).
>> 
>> The constructor/init/create function of the class/struct must allocate
>> the space needed for the instance, but it cannot use a static
>> allocation method (it doesn't know how many instances will be
>> requested).
>> 
>> One solution is to abandon encapsulation and expose the internal
>> definition of struct in the header file. In this way, the user (of the
>> class) can allocate directly the instance, by defining a variable.
>> 
>> Another solution is to implement a minimalistic malloc inside the class
>> source, maybe a simple memory pool where the number of elements are
>> defined at compile time.
>> 
>> Do you have better solutions?
>> 
>> 
>> 
>> [1] https://alastairs-place.net/blog/2013/06/03/encapsulation-in-c/
> 
> Typically using malloc is ok during system initialization time. An
> alternative to malloc are resource pools. Just allocate the needed
> resources when the system is booting up.

And never, ever, use free.  This is what I do, even with C++.  In 
general, the two problems with using the heap in an embedded system are 
memory fragmentation and outright using too much memory.  If you never 
use free you'll never run into the former, and if you make sure that you 
only allocate memory at startup, then if you DO run into the latter it 
should happen during development, when it's easy to fix (it should be 
predictable, too, with a bit of care).


-- 
Tim Wescott
Control systems, embedded software and circuit design
I'm looking for work!  See my website if you're interested
http://www.wescottdesign.com
0
Tim
12/21/2016 6:20:51 PM
Op 21-Dec-16 om 7:20 PM schreef Tim Wescott:
> On Wed, 21 Dec 2016 04:23:25 -0800, kalvin.news wrote:
>
>> keskiviikko 21. joulukuuta 2016 13.38.04 UTC+2 pozz kirjoitti:
>>> I know encapsulation tecnique is a Good Thing in coding. Encapsulation
>>> means writing write well separated modules, similar to classes in OO
>>> languages.
>>>
>>> Even in C, that isn't OO language, is possible to reach encapsulation
>>> by using a very simple ad effective trick: the instance of a "class" (C
>>> structure) is a pointer to the struct that isn't defined in .h (only
>>> typedef), but in .c.  For example, see here [1].
>>>
>>> IMHO it's a very good approach, however it's difficult to implement in
>>> embedded systems where you lack the presence of malloc (and you don't
>>> like to use it for many many reasons).
>>>
>>> The constructor/init/create function of the class/struct must allocate
>>> the space needed for the instance, but it cannot use a static
>>> allocation method (it doesn't know how many instances will be
>>> requested).
>>>
>>> One solution is to abandon encapsulation and expose the internal
>>> definition of struct in the header file. In this way, the user (of the
>>> class) can allocate directly the instance, by defining a variable.
>>>
>>> Another solution is to implement a minimalistic malloc inside the class
>>> source, maybe a simple memory pool where the number of elements are
>>> defined at compile time.
>>>
>>> Do you have better solutions?
>>>
>>>
>>>
>>> [1] https://alastairs-place.net/blog/2013/06/03/encapsulation-in-c/
>>
>> Typically using malloc is ok during system initialization time. An
>> alternative to malloc are resource pools. Just allocate the needed
>> resources when the system is booting up.
>
> And never, ever, use free.  This is what I do, even with C++.

Me too.

Typically I used something like

void free( void * p ){
    void you_silly_you_are_using_free();
    you_silly_you_are_using_free();
}

without a definition of you_silly_you_are_using_free().

(That is, if I use a heap at all.)

Wouter "Objects? No Thanks!" van Ooijen

0
Wouter
12/21/2016 9:46:58 PM
Am 21.12.2016 um 19:20 schrieb Tim Wescott:

> And never, ever, use free.  This is what I do, even with C++.

I would worry about that approach unless it's strictly a single-person 
project.  Letting people use malloc() but tabooing free(), OTOH, just 
feels a bit too much like handing a group of 5-year-olds some hand 
grenades after lecturing them there will be strictly no pulling of pins 
in this house.

 > In
> general, the two problems with using the heap in an embedded system are
> memory fragmentation and outright using too much memory.  If you never
> use free you'll never run into the former, and if you make sure that you
> only allocate memory at startup, then if you DO run into the latter it
> should happen during development, when it's easy to fix (it should be
> predictable, too, with a bit of care).

In most real-world applications, I'm convinced that handing out objects 
from a statically allocated pool per "class" achieves both those goals 
just as easily, while requiring less memory overhead.

In light of that, the only truly valid excuse for using malloc()/new in 
a memory constrained embedded device that I've heard of so far would be 
a use case where these conditions apply:

0) memory is constrained (no "virtual" memory, no swapping)
1) the whole system is regularly started from scratch
2) several separate pools of objects exist
3) those pools are not fully utilized during every "run"
4) you can impose rigid upper limits on individual pools' sizes
5) the sum of upper limits always exceeds providable memory
6) the sum of actual utilization will _never_ exceed provided memory

I can imagine that systems exist that fulfill 0) to 5). I find it very 
hard to believe that the full combination of 0) to 6) exists in the 
wild.  Condition 6) is effectively a unicorn --- the world might be 
nicer if it existed, but ...
0
UTF
12/21/2016 10:48:18 PM
Il 21/12/2016 18:06, Wouter van Ooijen ha scritto:
 > Op 21-Dec-16 om 12:38 PM schreef pozz:
 >> I know encapsulation tecnique is a Good Thing in coding. Encapsulation
 >> means writing write well separated modules, similar to classes in OO
 >> languages.
 >>
 >> Even in C, that isn't OO language, is possible to reach encapsulation by
 >> using a very simple ad effective trick: the instance of a "class" (C
 >> structure) is a pointer to the struct that isn't defined in .h (only
 >> typedef), but in .c.  For example, see here [1].
 >>
 >> IMHO it's a very good approach, however it's difficult to implement in
 >> embedded systems where you lack the presence of malloc (and you don't
 >> like to use it for many many reasons).
 >>
 >> The constructor/init/create function of the class/struct must allocate
 >> the space needed for the instance, but it cannot use a static allocation
 >> method (it doesn't know how many instances will be requested).
 >>
 >> One solution is to abandon encapsulation and expose the internal
 >> definition of struct in the header file. In this way, the user (of the
 >> class) can allocate directly the instance, by defining a variable.
 >>
 >> Another solution is to implement a minimalistic malloc inside the class
 >> source, maybe a simple memory pool where the number of elements are
 >> defined at compile time.
 >>
 >> Do you have better solutions?
 >
 > Use C++.
 >
 > (Just as with C, this means use *as suitable subset* of C++.)

I know C++ could be better (maybe Ada or...).  I think a discussion of 
the best programming language for embedded systems would be an entire 
different thread.

Staying on my question, how C++ helps? Of course it gives naturally 
encapsulation... but what about memory allocation and instance allocation?
0
pozz
12/21/2016 11:43:29 PM
On Thu, 22 Dec 2016 00:43:29 +0100, pozz wrote:

> Il 21/12/2016 18:06, Wouter van Ooijen ha scritto:
>  > Op 21-Dec-16 om 12:38 PM schreef pozz:
>  >> I know encapsulation tecnique is a Good Thing in coding.
>  >> Encapsulation means writing write well separated modules, similar to
>  >> classes in OO languages.
>  >>
>  >> Even in C, that isn't OO language, is possible to reach
>  >> encapsulation by using a very simple ad effective trick: the
>  >> instance of a "class" (C structure) is a pointer to the struct that
>  >> isn't defined in .h (only typedef), but in .c.  For example, see
>  >> here [1].
>  >>
>  >> IMHO it's a very good approach, however it's difficult to implement
>  >> in embedded systems where you lack the presence of malloc (and you
>  >> don't like to use it for many many reasons).
>  >>
>  >> The constructor/init/create function of the class/struct must
>  >> allocate the space needed for the instance, but it cannot use a
>  >> static allocation method (it doesn't know how many instances will be
>  >> requested).
>  >>
>  >> One solution is to abandon encapsulation and expose the internal
>  >> definition of struct in the header file. In this way, the user (of
>  >> the class) can allocate directly the instance, by defining a
>  >> variable.
>  >>
>  >> Another solution is to implement a minimalistic malloc inside the
>  >> class source, maybe a simple memory pool where the number of
>  >> elements are defined at compile time.
>  >>
>  >> Do you have better solutions?
>  >
>  > Use C++.
>  >
>  > (Just as with C, this means use *as suitable subset* of C++.)
> 
> I know C++ could be better (maybe Ada or...).  I think a discussion of
> the best programming language for embedded systems would be an entire
> different thread.
> 
> Staying on my question, how C++ helps? Of course it gives naturally
> encapsulation... but what about memory allocation and instance
> allocation?

A lot of what I do in C++ is to instantiate my classes where I need them, 
statically in files.

So, for instance, my "serial.cpp" file doesn't instantiate any serial 
interfaces.  Instead, my "menu.cpp" instantiates an object by including 
"serial.h" and then making an object that takes the port number in its 
constructor.

Wouter would have me write the serial port code such that the whole thing 
is a template class -- indeed, I may start doing that.

-- 

Tim Wescott
Wescott Design Services
http://www.wescottdesign.com

I'm looking for work -- see my website!
0
Tim
12/22/2016 12:04:38 AM
On 21/12/16 22:46, Wouter van Ooijen wrote:
> Op 21-Dec-16 om 7:20 PM schreef Tim Wescott:
>> On Wed, 21 Dec 2016 04:23:25 -0800, kalvin.news wrote:
>>
>>> keskiviikko 21. joulukuuta 2016 13.38.04 UTC+2 pozz kirjoitti:
>>>> I know encapsulation tecnique is a Good Thing in coding. Encapsulation
>>>> means writing write well separated modules, similar to classes in OO
>>>> languages.
>>>>
>>>> Even in C, that isn't OO language, is possible to reach encapsulation
>>>> by using a very simple ad effective trick: the instance of a "class" (C
>>>> structure) is a pointer to the struct that isn't defined in .h (only
>>>> typedef), but in .c.  For example, see here [1].
>>>>
>>>> IMHO it's a very good approach, however it's difficult to implement in
>>>> embedded systems where you lack the presence of malloc (and you don't
>>>> like to use it for many many reasons).
>>>>
>>>> The constructor/init/create function of the class/struct must allocate
>>>> the space needed for the instance, but it cannot use a static
>>>> allocation method (it doesn't know how many instances will be
>>>> requested).
>>>>
>>>> One solution is to abandon encapsulation and expose the internal
>>>> definition of struct in the header file. In this way, the user (of the
>>>> class) can allocate directly the instance, by defining a variable.
>>>>
>>>> Another solution is to implement a minimalistic malloc inside the class
>>>> source, maybe a simple memory pool where the number of elements are
>>>> defined at compile time.
>>>>
>>>> Do you have better solutions?
>>>>
>>>>
>>>>
>>>> [1] https://alastairs-place.net/blog/2013/06/03/encapsulation-in-c/
>>>
>>> Typically using malloc is ok during system initialization time. An
>>> alternative to malloc are resource pools. Just allocate the needed
>>> resources when the system is booting up.
>>
>> And never, ever, use free.  This is what I do, even with C++.
> 
> Me too.
> 
> Typically I used something like
> 
> void free( void * p ){
>    void you_silly_you_are_using_free();
>    you_silly_you_are_using_free();
> }
> 
> without a definition of you_silly_you_are_using_free().
> 
> (That is, if I use a heap at all.)
> 

You can do a little better than that, by declaring free as:

  void __attribute__((error("Don't use free"))) free(void*);

for gcc and compatible compilers, or

  [[deprecated("Don't use free!")]] void free(void*);

for C++ 14, if you don't have gcc.

That won't help if free is called indirectly, in which case you are
still relying on the linker failure.  But at least for your own code
that can #include these declarations, you'll get an error message (or at
least a "deprecated" warning) at compile time.


0
David
12/22/2016 8:22:09 AM
On 22/12/16 00:43, pozz wrote:
> Il 21/12/2016 18:06, Wouter van Ooijen ha scritto:
>> Op 21-Dec-16 om 12:38 PM schreef pozz:
>>> I know encapsulation tecnique is a Good Thing in coding. Encapsulation
>>> means writing write well separated modules, similar to classes in OO
>>> languages.
>>>
>>> Even in C, that isn't OO language, is possible to reach encapsulation by
>>> using a very simple ad effective trick: the instance of a "class" (C
>>> structure) is a pointer to the struct that isn't defined in .h (only
>>> typedef), but in .c.  For example, see here [1].
>>>
>>> IMHO it's a very good approach, however it's difficult to implement in
>>> embedded systems where you lack the presence of malloc (and you don't
>>> like to use it for many many reasons).
>>>
>>> The constructor/init/create function of the class/struct must allocate
>>> the space needed for the instance, but it cannot use a static allocation
>>> method (it doesn't know how many instances will be requested).
>>>
>>> One solution is to abandon encapsulation and expose the internal
>>> definition of struct in the header file. In this way, the user (of the
>>> class) can allocate directly the instance, by defining a variable.
>>>
>>> Another solution is to implement a minimalistic malloc inside the class
>>> source, maybe a simple memory pool where the number of elements are
>>> defined at compile time.
>>>
>>> Do you have better solutions?
>>
>> Use C++.
>>
>> (Just as with C, this means use *as suitable subset* of C++.)
> 
> I know C++ could be better (maybe Ada or...).  I think a discussion of
> the best programming language for embedded systems would be an entire
> different thread.
> 
> Staying on my question, how C++ helps? Of course it gives naturally
> encapsulation... but what about memory allocation and instance allocation?

For one thing, you override "new" for different classes so that you can
get a safe pool-based allocation while still using "new" in your code.

For some classes, you will only ever have one of them.  Such classes can
have a static buffer, and use that for their "new" - that lets you have
entirely statically allocated memory, but lets you use "new" to define
the construction order.

0
David
12/22/2016 8:29:42 AM
Op 22-Dec-16 om 1:04 AM schreef Tim Wescott:
> On Thu, 22 Dec 2016 00:43:29 +0100, pozz wrote:
>
>> Il 21/12/2016 18:06, Wouter van Ooijen ha scritto:
>>  > Op 21-Dec-16 om 12:38 PM schreef pozz:
>>  >> I know encapsulation tecnique is a Good Thing in coding.
>>  >> Encapsulation means writing write well separated modules, similar to
>>  >> classes in OO languages.
>>  >>
>>  >> Even in C, that isn't OO language, is possible to reach
>>  >> encapsulation by using a very simple ad effective trick: the
>>  >> instance of a "class" (C structure) is a pointer to the struct that
>>  >> isn't defined in .h (only typedef), but in .c.  For example, see
>>  >> here [1].
>>  >>
>>  >> IMHO it's a very good approach, however it's difficult to implement
>>  >> in embedded systems where you lack the presence of malloc (and you
>>  >> don't like to use it for many many reasons).
>>  >>
>>  >> The constructor/init/create function of the class/struct must
>>  >> allocate the space needed for the instance, but it cannot use a
>>  >> static allocation method (it doesn't know how many instances will be
>>  >> requested).
>>  >>
>>  >> One solution is to abandon encapsulation and expose the internal
>>  >> definition of struct in the header file. In this way, the user (of
>>  >> the class) can allocate directly the instance, by defining a
>>  >> variable.
>>  >>
>>  >> Another solution is to implement a minimalistic malloc inside the
>>  >> class source, maybe a simple memory pool where the number of
>>  >> elements are defined at compile time.
>>  >>
>>  >> Do you have better solutions?
>>  >
>>  > Use C++.
>>  >
>>  > (Just as with C, this means use *as suitable subset* of C++.)
>>
>> I know C++ could be better (maybe Ada or...).  I think a discussion of
>> the best programming language for embedded systems would be an entire
>> different thread.
>>
>> Staying on my question, how C++ helps? Of course it gives naturally
>> encapsulation... but what about memory allocation and instance
>> allocation?
>
> A lot of what I do in C++ is to instantiate my classes where I need them,
> statically in files.
>
> So, for instance, my "serial.cpp" file doesn't instantiate any serial
> interfaces.  Instead, my "menu.cpp" instantiates an object by including
> "serial.h" and then making an object that takes the port number in its
> constructor.
>
> Wouter would have me write the serial port code such that the whole thing
> is a template class -- indeed, I may start doing that.

Only when it needs parametrization.

Wouter "Objects? No Thanks!" van Ooijen

0
Wouter
12/22/2016 4:03:17 PM
On 12/21/16 6:38 AM, pozz wrote:
> I know encapsulation tecnique is a Good Thing in coding. Encapsulation
> means writing write well separated modules, similar to classes in OO
> languages.
>
> Even in C, that isn't OO language, is possible to reach encapsulation by
> using a very simple ad effective trick: the instance of a "class" (C
> structure) is a pointer to the struct that isn't defined in .h (only
> typedef), but in .c.  For example, see here [1].
>
> IMHO it's a very good approach, however it's difficult to implement in
> embedded systems where you lack the presence of malloc (and you don't
> like to use it for many many reasons).
>
> The constructor/init/create function of the class/struct must allocate
> the space needed for the instance, but it cannot use a static allocation
> method (it doesn't know how many instances will be requested).
>
> One solution is to abandon encapsulation and expose the internal
> definition of struct in the header file. In this way, the user (of the
> class) can allocate directly the instance, by defining a variable.
>
> Another solution is to implement a minimalistic malloc inside the class
> source, maybe a simple memory pool where the number of elements are
> defined at compile time.
>
> Do you have better solutions?
>
>
>
> [1] https://alastairs-place.net/blog/2013/06/03/encapsulation-in-c/

One technique that I have seen/used is the header that defines the 
opaque type also defines a structure that has been built to have the 
same alignment and size as the original, but not the 'real' definition 
(perhaps just a largest object then an array of char, or the right types 
but 'ugly' names (dummy1, dummy2, etc), and a check that its size 
matches in the real implementation file. That way client code can create 
a static object to pass to the init function that will have the right 
size, but the client code can't easily access the structure members.
0
Richard
12/24/2016 6:28:49 PM
Reply: