I have a function with a large number of out parameters which currenly looks as
int do_some_foo(char **string_out, int *index_out, char **description_out, etc...);
So since out parameters may grow and currently already about 8 in total (some of them omitted for brevity) I tend to group all the parameters into a struct and document that the caller does not own the out pointers
struct foo_out{
int status;
char *string;
int index;
char *description;
//...
};
//Pointers contained in the return value are not owned by
//the caller and should not be modified or reclaimed by it in
//any way
const struct foo_out *do_some_foo(int *error_code);
//Release all the resources used by the library
//all const struct foo_out * pointers returned by do_some_foo
//becomes invalid
void prepare_shutdown(void);
By this way I think I restricted the called from using this pointer after releasing resources used by the library. So the caller is not supposed to use the pointers after calling to it.