Static allocation and data hiding

Do you have a question? Post it now! No Registration Necessary

Translate This Thread From English to

Threaded View
It's a common problem in embedded projects. You want to hide private  
data of modules, but you don't want to use dynamic memory allocation.

In the .h file you write the typedef only and in .c file you write the  
full definition of the struct.
In this way you can't statically allocate the struct, because the  
compiler doesn't know the inner definition. If you want to use static  
allocation, you need to show the inner definition in the .h file, i.e.  
define it publicly.

FreeRTOS project uses another strategy. The real private definition is  
in the .c file, so hiding data. But the .h file has a dummy definition.

--- start of module.h ---
typedef struct myclass_s myclass;

typedef struct {
   uint8_t dummy1;
   uint16_y dummy2;
   char dummy3[24];
} static_myclass;

myclass *myclass_create_static(static_myclass *buf, uint8_t age,  
uint16_t sn, consr char *name);
--- end of module.h ---

--- start of module.c ---
struct myclass_s {
   uint8_t age;
   uint16_y serial_number;
   char name[24];
};

myclass *myclass_create_static(static_myclass *buf, uint8_t age,  
uint16_t sn, consr char *name) {
   myclass *obj = (myclass *)buf;
   obj->age = age;
   obj->serial_number = sn;
   memcpy(obj->name, name, sizeof(obj->name));
   return obj;
}
--- end of module.c ---


Do you have better strategies?

Re: Static allocation and data hiding
On 03/03/2021 13:16, pozz wrote:
Quoted text here. Click to load it



Quoted text here. Click to load it



Quoted text here. Click to load it





Quoted text here. Click to load it

Neither C nor C++ provide good features for data hiding like this -
FreeRTOS' method is perhaps the least bad way to get something that is
valid according to the rules for compatible types while also avoiding
the overhead of pointers and non-static data.  But it has the
disadvantage that the type needs to be defined twice, leading to
maintenance inconvenience.

With C++, you can do this:

    // myclass.h
    #include "myclass_imp.h"

    struct myclass : public myclass_imp {
        // Stuff you want to be documented and easily
        // seen by users of the class
    }



    // myclass_imp.h
    // Don't rely on the details in this file!!

    struct myclass_imp {
        // Hidden stuff
    }


People can still see the details in the class if they want to, but at
least it is a bit separate and out of the way.

(I don't bother with a second header for the implementation class - I
just put it in the second half of the main header.)
    

Re: Static allocation and data hiding
On 3/3/21 7:16 AM, pozz wrote:
Quoted text here. Click to load it

C provides at the language level data hiding only at a meta level. You
can define in your documentation what information the user is allowed to
assume is true, and what they shouldn't. You can perhaps use nameing
conventions to make it more obvious when that principle is being
violated (things like leading underscores in the name to mark things
that shouldn't be assumed to be promised). This goes in line with the
principle that C trusts the programmer, and is only trying to help fight
off Murphy and not Machiavelli.

The FreeRTOS method of dual structure definitions is one way to make
that naming much more obvious (using names like dummy1, but comes at the
cost of needing to maintain two concurrent versions of the structures,
and there HAVE been cases where the two have gotten out of sync (I don't
know if they have added a sizeof check to the C file to at least catch
the problem when it occurs).

It also comes at the cost that the program technically has undefined
behavior due to a violation of the One Definition Rule (The type of the
handle, and thus that type of that parameter to the functions, changes
depending on whether you are in implementation code or user code).

C++ improves this slightly, by allowing you to assign visibility
(public/protected/private) to members, and will generate an error if
someone accesses a member they aren't supposed to.

Other languages can hide the information more completely, put at the
cost that either you can't statically allocate the object (because you
need to know its size to allocate it) or the compiler needs a back door
that allows IT to peek at the full definition to get its size. The user
always has the option to peek at the source module if it is available,
or decode the compilers output to get information about the structure.

Often, the method provided by C is good enough, and you can always say
to the programmer that has their program break because the used
information they weren't supposed to use that its a problem of their own
making. (This presumes it isn't a security issue, but trusting in hiding
to provide security starts on a losing basis).

Site Timeline