In a response elsewhere, I found the following snippet:
In general it is nicer in C to have the caller allocate memory, not the callee - hence why strcpy is a "nicer" function, in my opinion, than strdup.
I can see how this is a valid pattern, but why might it be considered nicer? Are there advantages to following this pattern? Or not?
Recently I've written a fair amount of code that looks something like:
struct foo *a = foo_create();
// do something with a
foo_destroy(a);
If foo
is a anything more than a flat structure, then I figured I could put all my initialization in one step. Also, assume the struct should be on the heap. Why might it be better form to do something like:
struct foo *a = malloc(sizeof(foo));
foo_init(a);
// do something with a
foo_destroy(a)
Whenever you want an opaque structure and don't want to expose its internals in the header file. Your foo_create()
example illustrates this.
Another example is the Windows API. E.g. CreateWindow
gives you a HWND
. You have no idea what the actual WND
structure looks like and can't touch its fields.
Same with kernel object handles. E.g. CreateEvent
gives a HANDLE
. You can only manipulate it with the well-defined API, and close it with CloseHandle()
.
Re:
struct foo *a = malloc(sizeof(foo));
This requires you to define struct foo
in a header, and hence expose its internals. If you want to change it down the track, you risk breaking existing code that (incorrectly) relied on its members directly.
The main advantage of having the caller allocate the memory is that it simplifies the interface, and it's completely unambiguous that the caller owns the memory. As your create/destroy example shows, the simplification is not very great.
I prefer the create/destroy convention established by Dave Hanson in C Interfaces and Implementations:
struct foo *foo_new(...); // returns result of malloc()
void foo_free(struct foo **foop); // free *foop's resources and set *foop = NULL
You follow the convention thus:
struct foo *a = foo_new();
...
foo_free(&a);
// now `a` is guaranteed to be NULL
This convention makes it a little less likely you will leave a dangling pointer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With