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 keep
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.
Unfortunately, I think the typical way to deal with this problem is by simply having the programmer treat the object as opaque - the full structure implementation is in the header and available, it's just the responsibility of the programmer to not use the internals directly, only through the APIs defined for the object.
If this isn't good enough, a few options might be:
private
.extern
(ie., globals) Then have a special module that has access to the full definition of the object actually declare these objects. Since only the 'special' module has access to the full definition, the normal use of the opaque object remains opaque. However, now you have to rely on your programmers to not abuse the fact that thee objects are global. You have also increased the change of naming collisions, so that need to be managed (probably not a big problem, except that it might occur unintentionally - ouch!).I think overall, just relying on your programmers to follow the rules for the use of these objects might be the best solution (though using a subset of C++ isn't bad either in my opinion). Depending on your programmers to follow the rules of not using the structure internals isn't perfect, but it's a workable solution that is in common use.
One way would be to add something like
#define MODULE_HANDLE_SIZE (4711)
to the public module.h
header. Since that creates a worrying requirement of keeping this in sync with the actual size, the line is of course best auto-generated by the build process.
The other option is of course to actually expose the structure, but document it as being opaque and forbidding access through any other means than through the defined API. This can be made more clear by doing something like:
#include "module_private.h"
typedef struct
{
handle_private_t private;
} handle_t;
Here, the actual declaration of the module's handle has been moved into a separate header, to make it less obviously visible. A type declared in that header is then simply wrapped in the desired typedef
name, making sure to indicate that it is private.
Functions inside the module that take handle_t *
can safely access private
as a handle_private_t
value, since it's the first member of the public struct.