typedef opaque pointer to opaque pointer - c

I got the following code:
// file external_module.h
typedef externaldata * externalhdl; // opaque pointer
externalhdl external_Create();
// file internal_module.h
typedef internaldata * internalhdl; // opaque pointer
internalhdl internal_Create();
What i would like to do is to use an opaque pointer of a external module as a opaque pointer inside of my module to save unessasary allocs. Currently my workaround implimentation is:
typedef struct {externalhdl e} internaldata;
internalhdl internal_Create()
{
internalhdl p = (internaldata*) malloc (sizeof(internaldata));
p.e = external_Create();
return p;
}
What I would like to do is use something like:
typedef ??? internaldata; //Don't know how
internalhdl internal_Create()
{
return external_Create();
}
From my point of view it should be possible since both are pointer but I need to get it warning free? Thanks for your help.

The most important thing you need to consider in my opinion, is that you will gain absolutely nothing but darkenss in doing something like this, and that you want to typedef a pointer to another type of pointer. If it is an opaque poitner, it doesn't make sense to typedef it also because you will never access the members of the underlying structure, it might very well be passed as a void * pointer, but when you allocate it, you MUST know it's type because the compiler needs to know it's size and layout in order to allocate it correctly (aligning it correctly for example would be impossible otherwise).
If you don't want to repeatedly use the sizeof operator to allocate the correct size there are two possible approaches1
Use a macro
#define allocate(x) x = malloc(sizeof(*x))
and then
my_type *x;
allocate(x);
but this is horrible and unclear.
Use an allocation function,
my_type *
my_type_alloc()
{
return malloc(sizeof(my_type));
}
such that
my_type *x;
x = my_type_allocate();
this is clean and simple, and you can't do it wrong.
Note that returning the appropriate pointer type just ensures that you will not accidentally do something that might cause undefined behavior, but allocation functions can simply return void * and they will work, that is why I did not cast malloc()'s return value.
Syntax sugar is something that you must be very careful with, because somtimes it looks like you simplified and improved syntax when what you did was hide vital information from the fellow programmer that will read your code, that programmer could even be yourself some time after writing the code.
And your workaround is actually causing one unecessary allocation. In fact, when you finally understand poitners, you will then really avoid unnecessary allocations by not copying data when you will only read from it.
1In both cases, you should check for NULL after the allocation is performed to ensure you can access such pointer without causing undefined behavior

It would seem you are on the right track with the design, it is just the implementation that's questionable. As mentioned in comments, you should never hide pointers behind typedefs and opaque pointers is no exception to this. If the caller believes that these are allocated variables, they may decide to do stupid things like this:
set_obj(obj1, "foo"); // set private data to something
memcpy(&obj2, &obj1); // take a hardcopy of the data (or so we thought)
set_obj(obj1, "bar"); // set private data to something else
print_obj(obj2); // prints "bar", wtf!!!
So stop hiding the pointers.
With some slight modifications you should get the code to work as expected:
external.h
typedef struct external_t external_t;
external_t* external_create (/* parameters here */);
external.c
#include "external.h"
external_t* external_create (/* parameters here */)
{
external_t* ext = malloc(sizeof *ext);
/* initialize stuff here */
return ext;
}
internal.h
#include "external.h"
typedef struct internal_t internal_t;
internal_t* internal_create (/* parameters here */);
internal.c
#include "internal.h"
struct internal_t
{
external_t* ext;
};
internal_t* internal_create (/* parameters here */)
{
internal_t* inter = malloc(sizeof *inter);
inter->ext = external_create (/* parameters here */);
if(inter->ext == NULL)
{
return NULL;
}
/* initialize stuff here */
return inter;
}
The caller will have to use pointers too.
Also, there is no need to cast the result of malloc. Beat the dead horse here:
Do I cast the result of malloc?.

Related

Allocate space for struct pointer member through constructor

I want to use structs like objects in C.
Suppose I have the following:
typedef struct {
/* ... */
size_t *pages_len;
} book;
And I use the following method to construct it:
int book_init(/* some args... */, book * b) {
/* do some validation */
/* compute the number of pages n_pages */
b->pages_len = (size_t*) calloc(n_pages, sizeof(size_t));
/* compute pages_len based on some args */
return 0;
}
Then I construct an object like this:
book *my_book = (book*)malloc(sizeof(my_book));
if (book_init(/* some args */, my_book) == 0) {
/* do something */
}
And I destroy my object like: book_destroy(book *b) where I free(b->pages_len).
Is this correct or am I missing something? I can't show the original code but I am having trouble:
Accessing b->pages_len after the init method.
Destroying the object. I am having memory corruption.
As requested, a minimal reproducible example:
/* book.h */
#ifndef BOOK_HEADER_
#define BOOK_HEADER_
#include <ctype.h>
typedef struct
{
size_t pages_count;
size_t *pages_len;
} * book;
int book_create (book b);
#endif /* BOOK_HEADER_ */
/* book.c */
#include "book"
int
book_create (book b)
{
b->pages_len = calloc (3, sizeof (b->pages_len));
b->pages_len[2] = 20;
return 0;
}
/* test.c */
#include "book.h"
int main(int argc, char** argv) {
book my_book = (book)malloc (sizeof (book));
int r = book_create (my_book);
printf ("\n%lu\n", my_book->pages_len[2]);
free (my_book->pages_len);
free (my_book);
}
What I get from my memory leak detector is that free(my_book) gives a Memory corruption (written out of bounds?) error. One thing that fixed this error was changing the order of pages_count and pages_len but I don't know why.
I just typed the above example, so if there is any typo or syntactic error, please let me know. Thank you.
book my_book = malloc(sizeof(book)) is wrong. Note that the type of book is pointer to your struct, but you want to allocate enough space for the struct itself. So as the code stands, you will need to write malloc(sizeof(*my_book)).
However, using typedef to define a name for a pointer is usually bad style; it leads to confusion, and you will find it very awkward that your struct type doesn't have a name. A better way to write this would just be as
struct book
{
size_t pages_count;
size_t *pages_len;
};
struct book *my_book = malloc(sizeof(*my_book));
In this case malloc(sizeof(struct book)) would also work, but will become broken if you ever change the type of my_book.
It's often suggested that you not typedef away the struct, and just keep calling it struct book everywhere, because it's usually good to remember what kind of object you are working with. But if you must, you can still do typedef struct book book; afterwards. As mentioned, I would not recommend typedef struct book *book;.
Casting the result of malloc should never be necessary in C. You presumably included it because you got a warning about the return type of malloc, but the correct fix is to include the standard header <stdlib.h>. Indeed, this is precisely the reason why people usually recommend that you do not cast the result of malloc, because it can silence warnings that indicate a real bug. See Do I cast the result of malloc? for much more on this topic.
You also need <stdio.h> in test.c.
Also, create_book should return a value (but this is not the cause of your crash, since you never use it).
It is not surprising that rearranging the struct members made the bug appear to go away. What probably happened is something like this. On a typical 64-bit system, size_t and pointers are each 8 bytes. So you had allocated 8 bytes for your struct, when its size is actually 16. But you only actually wrote to the pages_len member. So if pages_len is the first member of the struct, and you never write to the pages_count member, you are only writing within the 8 bytes you allocated, and nothing goes wrong. Of course, the code was still broken, and as soon as you added any code that used the pages_count member, or added or rearranged any members of your struct, the bug would be back.
But in general, blindly changing things until a bug goes away is an extremely bad idea when programming in C. You may very easily do something that only masks the bug and makes it harder to find. There's no substitute for actually understanding what is happening.

which is better way to returning structure from function?

there are various ways to return structure from function like return whole structure or return the pointer only.
returning pointer is useful to avoid stack overhead as we don't needed to return whole structure. In other side for
small structure it is good to go with returning whole structure.
In my case i have below scenario to get structure from another file and thought various methods to use but as i am new to C so still i needed some expert advise like
which method is better? Any issue in it? or any suggestion for new method?
returning large structure as whole cause any stack issue?
file1.c
static struct_type mysruct; //Note : here struct size is 250+ bytes
//Method 1
struct_type getStructDataMethod1()
{
return mysruct;
}
//Method 2
void getStructDataMethod2(struct_type *structPtr)
{
if(structPtr != NULL)
{
memcpy(structPtr, &mysruct, sizeof(struct_type));
}
}
//Method 3
void getStructDataMethod3(struct_type *structPtr)
{
*structPtr = mysruct;
}
file2.c
void myFunction()
{
struct_type mylocalStruct1 = getStructDataMethod1();
struct_type mylocalStruct2;
struct_type mylocalStruct3;
getStructDataMethod2(&mylocalStruct2);
getStructDataMethod3(&mylocalStruct3);
}
The rule of thumb is to always pass structs to function by pointers and never by value, for the reasons you mention yourself. You should only make special case exceptions to this rule in case a struct is very small.
So either method 2 or 3 is the correct way to do it. Apart from the NULL pointer check, they are equivalent.
Minor issue not related to your question: never write functions as void myFunction() in C, this is obsolete style. Use void myFunction(void) instead.

C code passing struct into function Stack overflow

Okay so I'm having an issue with a current assignment (trust me this is a minuscule part of it) as we are required to write in C code and not C++, and we are not allowed to change certain parts of code. So I have a struct defined:
typedef struct someStruct {
int what;
int something[MAX];
int another[MAX];
} someType;
in main() I initialize all the values in a defined struct:
someType whatever, *whatptr;
EDIT:of course set the pointer to the struct, trying to simplify the code for the example It is present in my code already
whatptr = &whatever;
whatever.what = 0;
// initialize both arrays to hold 0 at all indexes
// Then I must call a function progRun()
progRun(); //I need to pass struct 'whatever' in some way
Now progRun() looks like this:
void progRun(){
printWhat(&whatever);
if (whatever.what == 0) {
//do stuff
}
}
I can't change anything inside this code except what parameters to pass inside the progRun() function and I can add stuff before printWhat(). I've tried changing progRun to
void progRun(someType *stptr)
then calling it in main as
progRun(whatptr);
but this causes a stack overflow issue for some reason, I've tried stepping through with a debugger and it only occurs when the function is called. Is there a better way to pass the 'whatever' struct to the function so it can be passed into progRun() and printWhat() and can access 'whatever.what'?
Any help would be greatly appreciated! in the meantime I'll try to figure it myself if I can.
EDIT: Something else must be wrong in the code even though everything else has compiled and ran perfectly fine until this code was added. If I can break down the code and find out what's wrong I'll update the question. And no I cannot post the whole code as it is an assignment (this isn't the goal of the assignment trust me it focuses on data forwarding and more, just need to get this basic thing working) Thank you for help everyone.
EDIT: the MAX number used in the struct for something[MAX] and another[MAX] was extremely large ( I left my desktop that I started this project with back home, I'm currently using an old laptop that can't handle large arrays). All the answers below, and some of the stuff I used before now works fine.
void progRun(someStruct *ptr) {
someStruct whatever2 = *ptr;
printWhat(whatever2);
if (whatever2.what == 0) { ...
}
whatptr = &whatever;
progRun(whatptr);
Your problem was that:
you need to pass a pointer to whatever, yet you were passing a variable (whatptr) that had absolutely nothing to do with whatever.
You need to first assign the pointer to whatever into your pointer variable.
You are not dereferencing the pointer in the function
Alternately, get rid of pointer variables:
void progRun(someType *stptr) {
printWhat(*stptr);
if (stptr->what == 0) { ...
}
progRun(&whatever);
Instruction
someType whatever, *whatptr;
is the problem:
*whatptr will not point to the struct whatever unless you do the assignment as follows:
whatptr = &whatever;
Alternatively you could dynamically allocate memory on the heap for a pointer to your struct whatever by using the malloc() function and pass the pointer returned by malloc to the function progrun:
whatptr = (someType*) malloc ( sizeof(someType) );
if (whatptr == NULL) exit (1);
//whatever you need to do with your code
progrun(whatptr); // call function like this
In this case of course you will need to dereference your pointer to access member elements of the struct by using the arrow -> operator:
whatpr->what = 0; // for example
Also, check these tutorials to understand both approaches:
link 1
link 2
If you can't change print and if statements then you should pass your function a copy of your struct:
void progRun( someType whatever ){ // <---Passing by copy
printWhat(&whatever);
if (whatever.what == 0) {
//do stuff
}
}
and in your main() you should just call the function like this:
someType whatever;
//assign values to members of the struct
progRun(whatever);
and do not need at all to define and assign a pointer to the struct.
Though passing variables to functions by copy (especially when they are objects composed by many variables such as a struct is) is not a good behaviour:
it will require an overhead to copy all member elements
your copy will have a limited scope, which means that any change you do to the variable inside of the function will be lost when your function ends and will not be reflected on variable at main scope

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).
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;
size_t get_size();
something* create_something(void* mem);
// Usage
something* ptr = create_something(_alloca(get_size())); // or define a macro.
// Implementation
size_t get_size() {
return sizeof(real_handle_type);
}
something* create_something(void* mem) {
real_handle_type* ptr = (real_handle_type*)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.
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.
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:
use C++ as a 'better C' and declare the internals of the structure as private.
run some sort of pre-processor on the headers so that the internals of the structure are declared, but with unusable names. The original header, with good names, will be available to the implementation of the APIs that manage the structure. I've never seen this technique used - it's just an idea off the top of my head that might be possible, but seems like far more trouble than it's worth.
have your code that uses opaque pointers declare the statically allocated objects as 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 solution if to create a static pool of struct handle_t objects, and provide then as neceessary. There are many ways to achieve that, but a simple illustrative example follows:
// In file module.c
struct handle_t
{
int foo;
void* something;
int another_implementation_detail;
int in_use ;
} ;
static struct handle_t handle_pool[MAX_HANDLES] ;
handle_t* create_handle()
{
int h ;
handle_t* handle = 0 ;
for( h = 0; handle == 0 && h < MAX_HANDLES; h++ )
{
if( handle_pool[h].in_use == 0 )
{
handle = &handle_pool[h] ;
}
}
// other initialization
return handle;
}
void release_handle( handle_t* handle )
{
handle->in_use = 0 ;
}
There are faster faster ways of finding an unused handle, you could for example keep a static index that increments each time a handle is allocated and 'wraps-around' when it reaches MAX_HANDLES; this would be faster for the typical situation where several handles are allocated before releasing any one. For a small number of handles however, this brute-force search is probably adequate.
Of course the handle itself need no longer be a pointer but could be a simple index into the hidden pool. This would enhance data hiding and protection of the pool from external access.
So the header would have:
typedef int handle_t ;
and the code would change as follows:
// In file module.c
struct handle_s
{
int foo;
void* something;
int another_implementation_detail;
int in_use ;
} ;
static struct handle_s handle_pool[MAX_HANDLES] ;
handle_t create_handle()
{
int h ;
handle_t handle = -1 ;
for( h = 0; handle != -1 && h < MAX_HANDLES; h++ )
{
if( handle_pool[h].in_use == 0 )
{
handle = h ;
}
}
// other initialization
return handle;
}
void release_handle( handle_t handle )
{
handle_pool[handle].in_use = 0 ;
}
Because the handle returned is no longer a pointer to the internal data, and inquisitive or malicious user cannnot gain access to it through the handle.
Note that you may need to add some thread-safety mechanisms if you are getting handles in multiple threads.
I faced a similar problem in implementing a data structure in which the header of the data structure, which is opaque, holds all the various data that needs to be carried over from operation to operation.
Since re-initialization might cause a memory leak, I wanted to make sure that data structure implementation itself never actually overwrite a point to heap allocated memory.
What I did is the following:
/**
* In order to allow the client to place the data structure header on the
* stack we need data structure header size. [1/4]
**/
#define CT_HEADER_SIZE ( (sizeof(void*) * 2) \
+ (sizeof(int) * 2) \
+ (sizeof(unsigned long) * 1) \
)
/**
* After the size has been produced, a type which is a size *alias* of the
* header can be created. [2/4]
**/
struct header { char h_sz[CT_HEADER_SIZE]; };
typedef struct header data_structure_header;
/* In all the public interfaces the size alias is used. [3/4] */
bool ds_init_new(data_structure_header *ds /* , ...*/);
In the implementation file:
struct imp_header {
void *ptr1,
*ptr2;
int i,
max;
unsigned long total;
};
/* implementation proper */
static bool imp_init_new(struct imp_header *head /* , ...*/)
{
return false;
}
/* public interface */
bool ds_init_new(data_structure_header *ds /* , ...*/)
{
int i;
/* only accept a zero init'ed header */
for(i = 0; i < CT_HEADER_SIZE; ++i) {
if(ds->h_sz[i] != 0) {
return false;
}
}
/* just in case we forgot something */
assert(sizeof(data_structure_header) == sizeof(struct imp_header));
/* Explicit conversion is used from the public interface to the
* implementation proper. [4/4]
*/
return imp_init_new( (struct imp_header *)ds /* , ...*/);
}
client side:
int foo()
{
data_structure_header ds = { 0 };
ds_init_new(&ds /*, ...*/);
}
To expand on some old discussion in comments here, you can do this by providing an allocator function as part of the constructor call.
Given some opaque type typedef struct opaque opaque;, then
Define a function type for an allocator function typedef void* alloc_t (size_t bytes);. In this case I used the same signature as malloc/alloca for compatibility purposes.
The constructor implementation would look something like this:
struct opaque
{
int foo; // some private member
};
opaque* opaque_construct (alloc_t* alloc, int some_value)
{
opaque* obj = alloc(sizeof *obj);
if(obj == NULL) { return NULL; }
// initialize members
obj->foo = some_value;
return obj;
}
That is, the allocator gets provided the size of the opaque object from inside the constructor, where it is known.
For static storage allocation like done in embedded systems, we can create a simple static memory pool class like this:
#define MAX_SIZE 100
static uint8_t mempool [MAX_SIZE];
static size_t mempool_size=0;
void* static_alloc (size_t size)
{
uint8_t* result;
if(mempool_size + size > MAX_SIZE)
{
return NULL;
}
result = &mempool[mempool_size];
mempool_size += size;
return result;
}
(This might be allocated in .bss or in your own custom section, whatever is preferred.)
Now the caller can decide how each object is allocated and all objects in for example a resource-constrained microcontroller can share the same memory pool. Usage:
opaque* obj1 = opaque_construct(malloc, 123);
opaque* obj2 = opaque_construct(static_alloc, 123);
opaque* obj3 = opaque_construct(alloca, 123); // if supported
This is useful for the purpose of saving memory. In case you have multiple drivers in a microcontroller application and each makes sense to hide behind a HAL, they can now share the same memory pool without the driver implementer having to speculate how many instances of each opaque type that will be needed.
Say for example that we have generic HAL for hardware peripherals to UART, SPI and CAN. Rather than each implementation of the driver providing its own memory pool, they can all share a centralized section. Normally I would otherwise solve that by having a constant such as UART_MEMPOOL_SIZE 5 exposed in uart.h so that the user may change it after how many UART objects they need (like the the number of present UART hardware peripherals on some MCU, or the number of CAN bus message objects required for some CAN implementation etc etc). Using #define constants is an unfortunate design since we typically don't want application programmers to mess around with provided standardized HAL headers.
I'm a little confused why you say you can't use malloc(). Obviously on an embedded system you have limited memory and the usual solution is to have your own memory manager which mallocs a large memory pool and then allocates chunks of this out as needed. I've seen various different implementations of this idea in my time.
To answer your question though, why don't you simply statically allocate a fixed size array of them in module.c add an "in-use" flag, and then have create_handle() simply return the pointer to the first free element.
As an extension to this idea, the "handle" could then be an integer index rather than the actual pointer which avoids any chance of the user trying to abuse it by casting it to their own definition of the object.
The least grim solution I've seen to this has been to provide an opaque struct for the caller's use, which is large enough, plus maybe a bit, along with a mention of the types used in the real struct, to ensure that the opaque struct will be aligned well enough compared to the real one:
struct Thing {
union {
char data[16];
uint32_t b;
uint8_t a;
} opaque;
};
typedef struct Thing Thing;
Then functions take a pointer to one of those:
void InitThing(Thing *thing);
void DoThingy(Thing *thing,float whatever);
Internally, not exposed as part of the API, there is a struct that has the true internals:
struct RealThing {
uint32_t private1,private2,private3;
uint8_t private4;
};
typedef struct RealThing RealThing;
(This one just has uint32_t' anduint8_t' -- that's the reason for the appearance of these two types in the union above.)
Plus probably a compile-time assert to make sure that RealThing's size doesn't exceed that of Thing:
typedef char CheckRealThingSize[sizeof(RealThing)<=sizeof(Thing)?1:-1];
Then each function in the library does a cast on its argument when it's going to use it:
void InitThing(Thing *thing) {
RealThing *t=(RealThing *)thing;
/* stuff with *t */
}
With this in place, the caller can create objects of the right size on the stack, and call functions against them, the struct is still opaque, and there's some checking that the opaque version is large enough.
One potential issue is that fields could be inserted into the real struct that mean it requires an alignment that the opaque struct doesn't, and this won't necessarily trip the size check. Many such changes will change the struct's size, so they'll get caught, but not all. I'm not sure of any solution to this.
Alternatively, if you have a special public-facing header(s) that the library never includes itself, then you can probably (subject to testing against the compilers you support...) just write your public prototypes with one type and your internal ones with the other. It would still be a good idea to structure the headers so that the library sees the public-facing Thing struct somehow, though, so that its size can be checked.
It is simple, simply put the structs in a privateTypes.h header file. It will not be opaque anymore, still, it will be private to the programmer, since it is inside a private file.
An example here:
Hiding members in a C struct
This is an old question, but since it's also biting me, I wanted to provide here a possible answer (which I'm using).
So here is an example :
// file.h
typedef struct { size_t space[3]; } publicType;
int doSomething(publicType* object);
// file.c
typedef struct { unsigned var1; int var2; size_t var3; } privateType;
int doSomething(publicType* object)
{
privateType* obPtr = (privateType*) object;
(...)
}
Advantages :
publicType can be allocated on stack.
Note that correct underlying type must be selected in order to ensure proper alignment (i.e. don't use char).
Note also that sizeof(publicType) >= sizeof(privateType).
I suggest a static assert to make sure this condition is always checked.
As a final note, if you believe your structure may evolve later on, don't hesitate to make the public type a bit bigger, to keep room for future expansions without breaking ABI.
Disadvantage :
The casting from public to private type can trigger strict aliasing warnings.
I discovered later on that this method has similarities with struct sockaddr within BSD socket, which meets basically the same problem with strict aliasing warnings.

Pointers to void pointers in C - can I use void** for rudimentary polymorphism?

I can understand how a void** might look in memory, but I'm wondering if I'm using it quite right. Are there any fundamental flaws in what I describe below? For example, although I can say "it works for me", am I creating bad / unportable code in some way?
So I have an Asteroids clone. There are three entities that can fire bullets, the players (SHIP *player_1, SHIP *player_2) and the UFO (UFO *ufo). When a bullet is fired, it's important to know who fired the bullet; if it was a player, when it hits something their score needs to be incremented. So, the bullet will store what kind of entity it belongs to (owner_type) and also a pointer directly to the owner (owner):
enum ShipType
{
SHIP_PLAYER,
SHIP_UFO
};
typedef struct Bullet
{
// ...other properties
enum ShipType owner_type;
void **owner;
} BULLET;
Then, when the player hits the button or the UFO sees a target, one of these functions will be called:
void ship_fire(SHIP **shipp)
{
BULLET *bullet = calloc(1, sizeof(BULLET));
bullet->owner_type = SHIP_PLAYER;
bullet->owner = (void**)shipp;
// do other things
}
void ufo_fire(UFO **ufop)
{
BULLET *bullet = calloc(1, sizeof(BULLET));
bullet->owner_type = SHIP_UFO;
bullet->owner = (void**)ufop;
// do other things
}
... they may be called, for example, like this:
ship_fire(&player_1);
Finally, when the bullet hits a target (such as an asteroid), we dereference the owner. If it's a ship, we can increment the score there and then.
void hit_asteroid(ASTEROID *ast, BULLET *bullet)
{
SHIP *ship_owner;
if (bullet->owner_type == SHIP_PLAYER && *bullet->owner != NULL)
{
ship_owner = (SHIP*)*bullet->owner;
ship_owner->score += 1000;
}
}
Does that seem a reasonable approach? Like I say, it works for me, but I only have a couple of months of C experience.
A final note: why do I not use a void* instead of a void**? Because I want to avoid dangling pointers. In other words, say that player_1 dies and is free'd, but their bullet keeps going and hits an asteroid. If I only have a void*, the hit_asteroid function has no way of knowing that bullet->owner points to de-allocated memory. But with a void**, I can validly check to see if it's NULL; if player_1 is NULL, then *bullet->owner will be NULL too.
EDIT: All respondents so far concur that using a void** probably isn't necessary here because I can avoid the dangling pointers issue (by just statically allocating the base object, for instance). They're correct and I will refactor. But I'm still kinda interested to know if I've used void** in a way that might break something e.g. in terms of memory allocation / casting. But I guess if no-one has thrown their hands in the air and declared it faulty, it at least resembles something that would technically work.
Thanks!
Even if you wanted to continue doing it the way you were, you don't need to use void ** (and shouldn't).
Although void * is a generic pointer type, void ** is not a generic pointer-to-pointer type - it should always point to a genuine void * object. Your code dereferences a SHIP ** or UFO ** pointer through an lvalue of type void ** - that's technically not guaranteed to work. (This happens when you do (SHIP*)*bullet->owner).
However, the good news is that you could continue to use the double-pointer method, using a plain void * to do the job. void * can happily store a pointer-to-a-pointer (because that, after all, is just another kind of pointer). If you change owner to void *, then in ship_fire you would do this:
bullet->owner = shipp;
and in hit_asteroid you would do this:
ship_owner = *(SHIP **)bullet->owner;
In general, the rule for working with pointer casts is: First cast the pointer back to the pointer type that you know it really is, then dereference.
The linux kernel does this in an interesting way. It would be something like
/**
* container_of - cast a member of a structure out to the containing structure
* #ptr: the pointer to the member.
* #type: the type of the container struct this is embedded in.
* #member: the name of the member within the struct.
*
*/
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
typedef struct Ship {
void (*fire)(struct Ship * shipp);
/* ...other methods...*/
} SHIP;
#define playership_of(shipp) container_of(shipp, PLAYERSHIP, ship)
#define ufoship_of(shipp) container_of(shipp, UFOSHIP, ship)
typedef struct PlayerShip {
/* PlayerShip specific stuff ...*/
SHIP ship;
/*...*/
} PLAYERSHIP;
typedef struct UFOShip {
/*...UFO stuff...*/
SHIP ship;
/*...*/
} UFOSHIP;
void ship_fire(SHIP * shipp)
{
shipp->fire(shipp);
}
void player_fire(SHIP *shipp)
{
PLAYERSHIP * ps = playership_of(shipp);
BULLET *bullet = calloc(1, sizeof(BULLET));
bullet->owner = shipp;
// do other things
}
void ufo_fire(SHIP * shipp)
{
UFOSHIP * ufos = ufoship_of(shipp);
BULLET *bullet = calloc(1, sizeof(BULLET));
bullet->owner = ufop;
// do other things
}
UFOSHIP ufoship = { /*...*/ .ship = { .fire = ufo_fire } /* ... */ };
PLAYERSHIP playership = { /*...*/ .ship = { .fire = player_fire } /*...*/ };
/* ... */
ship_fire(&playership.ship);
Read the linux kernel source code for lots of examples of this tecnique.
Since you only have two possible types, I'd use a union for this sort of thing, like so:
typedef struct Bullet {
enum ShipType owner_type;
union {
SHIP *ship;
UFO *ufo;
} owner;
} BULLET;
/* and then... */
void hit_asteroid(ASTEROID *ast, BULLET *bullet)
{
SHIP *ship_owner;
if (bullet->owner_type == SHIP_PLAYER && bullet->owner.ship != NULL) {
ship_owner = bullet->owner.ship;
ship_owner->score += 1000;
}
}
Note that I didn't use the pointer-to-a-pointer scheme that you used. I'm not really convinced of the necessity of it, and the code I suggested doesn't require such a technique.
First off, check the union construct suggested by mipadi; that's a very readable and efficient way of dealing with polymorphism.
Closer to your snippet/question, at a quick glance, I don't see the need/use for the double indirection introduced by pointer-to-pointers. The whole logic would work the same if the arguments to xxxx_fire() methods were [direct] pointers to xxxx objects (and if the typecast etc. in the rest of the logic were to follow accordingly.
Pointers to pointers are useful when the value of the intermediate pointer may be changed at some point. For example if the underlying object is moved, or if it replace by a different object altogether (say a better-equipped ship part of a new level in game etc...)
Edit: (on the use of double indirection to manage "fleets" of objects which may be deallocated.
Responding to your comment, do not refactor so that the objects are not de-allocated (from memory) when they get killed/detroyed (as part of the game). Instead, look into something like the following, as this is indeed an example where the pointer-to-pointer construct helps a lot. Here's how it could work:
Upon game (or level) initialization, allocate an array of pointers big enough to contain as many pointers as the total number of objects the game may allocate, over time. Initialize all its values to NULL.
Introduce an int value index, which indicates the location of the next available (=unused so far) pointer in this array.
When a new object (UFO, Ship or what have you) gets created, four things happen:
new memory is allocated for the object per se
the address of this new memory is stored in the object pointer array (at the location indicated by the index)
the index gets incremented
the "world" only knows this object by way of the double indirection
when an object gets destroyed two things happen
the memory is freed
the pointer in the array is set to null
when accessing any objects the program does three things
first dereference (once) the pointer-to-pointer
check if this is null (if so this indicate the object doesn't exist anymore, the logic may decide to remove this reference from wherever it stored it, as so to not try again, but this is of course optional).
access the actual object by dereferencing the intermediate pointer (if it isn't NULL)
In insight, a short snippet in C language may have been more explicit; sorry I described this in words...
If your bullet owners are frequently changed (e.g. deallocated), the pointer-to-pointer approach is suitable. The union solution does not address this concern directly; as presented, it does not support deallocating ships without touching the pointer on each of that ship's bullets. Of course, that may actually be a practical solution in some implementations, e.g. if you have a need to find all the bullets of a given player, you could maintain a linked list of them: a “next_bullet” pointer for each bullet and “last_bullet” pointer to the head of the list for each player.
And instead of allocating each bullet separately, I would also follow mjv's suggestion of pre-allocating some number of them and picking the next available one. In the linked list implementation, you could use the same “next_bullet” pointers to maintain one list of pre-allocated bullets not currently in use. The advantage of this approach is that you could easily allocate more if you ran out of them, instead of maintaining an array, i.e. if the list of available bullets is empty just add them to the list on demand. Similarly, put “expired” (exploded?) bullets back into the list of available ones and the amount allocated will automatically adapt to however many is required.
Another thing that comes to mind is that you might not need to know which particular UFO (or other enemy) owns a given bullet; just have a single pointer (e.g. SHIP **) for the owning player and set it to NULL for all non-player bullets. If this is not suitable, you could also consider storing the type of each owner in the beginning of owner struct itself, e.g.:
enum EntityType { TYPE_PLAYER_SHIP, TYPE_UFO_SHIP, TYPE_BULLET, };
struct GameEntity {
enum EntityType type;
// This struct is not actually used, it just defines the beginning
};
struct Ship {
enum EntityType type; // Set to TYPE_PLAYER_SHIP when allocating!
…
};
struct UFO {
enum EntityType type; // Set to TYPE_UFO_SHIP when allocating!
…
};
struct Bullet {
enum EntityType type; // Set to TYPE_BULLET when allocating!
struct GameEntity *owner;
…
};
struct Bullet *ship_fire (struct Ship *ship) {
Bullet *b = get_next_available_bullet();
b->owner = (struct GameEntity *) ship;
return b;
}
void hit_asteroid (struct Asteroid *ast, struct Bullet *bullet) {
if (bullet->owner && bullet->owner->type == TYPE_PLAYER_SHIP) {
…
}
}
Note that this trick relies on pointers to different types of structs being interchangeable, and the single enum being stored at the same offset in each type of struct. In practice these are not unreasonable assumptions, but I'm not certain that this behaviour is strictly guaranteed in standard C (however, e.g. struct sockaddr uses the same trick, and it's used by various POSIX networking functions like bind).
I would do like this:
enum _ShipType
{
SHIPT_PLAYER,
SHIPT_UFO, //trailing , is good if you need to add types later
};
typedef struct _Bullet
{
// ...other properties
struct _Bullet_Owner
{
enum _ShipType type;
void* ship;
}owner;
} Bullet;
void ship_fire(Player* p)
{
Bullet* b = malloc(sizeof(Bullet));
// ...other init
b->owner.type = SHIPT_PLAYER;
b->owner.ship = p;
}
If there's only <constant> players, you would be better off having a dead flag for each and setting when they die. (And having them statically allocated.)
#define PLF_DEAD 0x1
//more stuff
struct _Player
{
long flags;
//other data;
}player_1,player_2;
Or you could have an array, or...
Edit: Nonconstant players, a horrifically overengineered solution:
typedef struct _PShip
{
long nweakrefs;
void** weakrefs;
//etc...
}PShip;
PShip* PShip_new(/* args or void */)
{
PShip t;
t = malloc(sizeof(PShip));
t->nweakrefs = 1;
t->weakrefs = malloc(sizeof(void*)*t->nweakrefs);
//other stuff
}
void PShip_regref(PShip** ref)
{
void** temp;
temp = realloc((*ref)->weakrefs,(*ref)->nweakrefs);
if(!temp){/* handle error somehow */}
(*ref)->weakrefs = temp;
(*ref)->weakrefs[(*ref)->nweakrefs++] = ref;
}
void PShip_free(PShip* ship)
{
long i;
for(i=0;i<ship->nweakrefs;i++)
{
if(ship->weakrefs[i]){*(ship->weakrefs[i]) = 0;}
}
//other stuff
}
Alternatively, a reference count might work well, without the O(n) memory.
typedef struct _PShip
{
long refs;
//etc...
}PShip;
void Bullet_free(Bullet* bullet)
{
//other stuff
if(bullet->owner.type == SHIPT_PLAYER)
{
if(--(((PShip*)(bullet->owner.ship))->refs) <= 0)
{PShip_free(bullet->owner.ship);}
}
}
Also, neither of these is threadsafe.

Resources