Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Static allocation of opaque data types

Very often malloc() is absolutely not allowed when programming for embedded systems. Most of the time I'm pretty able to deal with this, but one thing irritates me: it keeps me from using so called 'opaque types' to enable data hiding. Normally I'd do something like this:

// In file module.h typedef struct handle_t handle_t;  handle_t *create_handle(); void operation_on_handle(handle_t *handle, int an_argument); void another_operation_on_handle(handle_t *handle, char etcetera); void close_handle(handle_t *handle);   // In file module.c struct handle_t {     int foo;     void *something;     int another_implementation_detail; };  handle_t *create_handle() {     handle_t *handle = malloc(sizeof(struct handle_t));     // other initialization     return handle; } 

There you go: create_handle() performs a malloc() to create an 'instance'. A construction often used to prevent having to malloc() is to change the prototype of create_handle() like this:

void create_handle(handle_t *handle); 

And then the caller could create the handle this way:

// In file caller.c void i_am_the_caller() {     handle_t a_handle;    // Allocate a handle on the stack instead of malloc()     create_handle(&a_handle);     // ... a_handle is ready to go! } 

But unfortunately this code is obviously invalid, the size of handle_t isn't known!

I never really found a solution to solve this in a proper way. I'd very like to know if anyone has a proper way of doing this, or maybe a complete different approach to enable data hiding in C (not using static globals in the module.c of course, one must be able to create multiple instances).

like image 689
Bart Avatar asked Dec 14 '10 14:12

Bart


People also ask

What is an opaque data structure?

In computer science, an opaque data type is a data type whose concrete data structure is not defined in an interface. This enforces information hiding, since its values can only be manipulated by calling subroutines that have access to the missing information.

What is opaque type in C?

Opaque types are, in part, a way to make C more object-oriented. They allow encapsulation, so that the internal details of a type can change--or be implemented differently in different platforms/situations--without the code that uses it having to change.

What does opaque value mean?

"Opaque" is defined, in English, as "not able to be seen through; not transparent". In Computer Science, this means a value which reveals no details other then the type of the value itself.


1 Answers

You can use the _alloca function. I believe that it's not exactly Standard, but as far as I know, nearly all common compilers implement it. When you use it as a default argument, it allocates off the caller's stack.

// Header typedef struct {} something; int get_size(); something* create_something(void* mem);  // Usage handle* ptr = create_something(_alloca(get_size()); // or define a macro.  // Implementation int get_size() {     return sizeof(real_handle_type); } something* create_something(void* mem) {     real_type* ptr = (real_type_ptr*)mem;     // Fill out real_type     return (something*)mem; } 

You could also use some kind of object pool semi-heap - if you have a maximum number of currently available objects, then you could allocate all memory for them statically, and just bit-shift for which ones are currently in use.

#define MAX_OBJECTS 32 real_type objects[MAX_OBJECTS]; unsigned int in_use; // Make sure this is large enough something* create_something() {      for(int i = 0; i < MAX_OBJECTS; i++) {          if (!(in_use & (1 << i))) {              in_use &= (1 << i);              return &objects[i];          }      }      return NULL; } 

My bit-shifting is a little off, been a long time since I've done it, but I hope that you get the point.

like image 162
Puppy Avatar answered Sep 20 '22 06:09

Puppy