In general, it's important that the library documents the 'contract' it makes with the applications that are using its service. The library writer documents all the allocations made by the library and what needs to be freed by the application. Like any contract, it's good when it is simple and consistent.
In this particular case, I suppose the library should also offer:
void free_bs(bs *b)
{
if (b->d) {
/* free b->d here */
}
/* free rest of the structure */
}
which frees the structure. It makes sense to also free the d array here. The application has pointer to all the bs
structures and is responsible for calling free_bs
on them when no longer needed.
If, for example, you want to keep d for future usage, after you're done with the library operation, the contract is a bit more complex. The library could also provide:
double** bs_get_data(bs *b)
{
double **d = b->d;
b->d = NULL;
return b->d;
}
which returns a pointer to d
, and leaves the field empty so that the free routine knows to skip it.
The docs for the bs_get_data()
have to explain that it can be called only once, and that the application takes the responsibility of freeing the array in this case.
UPDATE:
In answer to your comment below: First of all, please note that I simplified the problem by assuming (at least) the following: the d
is referenced either by a single bs
structure or by the application. The application and the library "pass" a single reference to the array from one to the other. If you want the same d
array in more bs
structures, for example, than my approach is not enough.
The flag that you propose in the comment might help, but is not standard practice, FWIK. In this case, I would suggest to implement some simple reference counting. If d
is the resource that needs to be shared around, make it an "object":
typedef struct {
double **d;
int ref;
} d_t;
Initialize ref
with 1. In new_bs()
and in all functions that receive a "copy" of d
, increment the reference count. When the bs
structure gets deleted, or when you no longer need d
in your application, decrement it's reference count. If it gets to zero, free it. In a way, it is what the high level languages do for you, and is very efficient in keeping the resource management sane.
So no one is owning the array, but whoever needs it last, frees it.
Of course, this requires more work and complicates code, so try to put in balance. It's not needed for every structure you have, but only for those you need to keep multiple references to.