C API design: Who should allocate?

Tordek picture Tordek · Jul 21, 2010 · Viewed 7.6k times · Source

What is the proper/preferred way to allocate memory in a C API?

I can see, at first, two options:

1) Let the caller do all the (outer) memory handling:

myStruct *s = malloc(sizeof(s));
myStruct_init(s);

myStruct_foo(s);

myStruct_destroy(s);
free(s);

The _init and _destroy functions are necessary since some more memory may be allocated inside, and it must be handled somewhere.

This has the disadvantage of being longer, but also the malloc can be eliminated in some cases (e.g., it can be passed a stack-allocated struct:

int bar() {
    myStruct s;
    myStruct_init(&s);

    myStruct_foo(&s);

    myStruct_destroy(&s);
}

Also, it's necessary for the caller to know the size of the struct.

2) Hide mallocs in _init and frees in _destroy.

Advantages: shorter code, since the functions are going to be called anyway. Completely opaque structures.

Disadvantages: Can't be passed a struct allocated in a different way.

myStruct *s = myStruct_init();

myStruct_foo(s);

myStruct_destroy(foo);

I'm currently leaning for the first case; then again, I don't know about C API design.

Answer

JeremyP picture JeremyP · Jul 21, 2010

Method number 2 every time.

Why? because with method number 1 you have to leak implementation details to the caller. The caller has to know at least how big the struct is. You can't change the internal implementation of the object without recompiling any code that uses it.