开发者

Memory allocation included in API

If there is the 'struct foo' and an APIs which handle foo, which is more flexible and convenient API?

1) API only initialize foo. User should declare foo or allocate memory for foo. The this style is like pthread_mutex_init/pthread_mutex_destroy.

example 1)

struct foo a;
init_foo(&a);'

example 2)

struct foo *a;
a = malloc(sizeof(struct foo));
init开发者_开发技巧_foo(a);

2) API allocates memory and user get the pointer. This is like getaddrinfo/freeaddrinfo.

example)

struct foo *a;
get_foo(&a);
put_foo(a);


It really depends on the API. The first has the advantage that the user can embed the library type in his own structures without any indirection if that is beneficial; on the other hand the type of the structure must be completely known to the library user making any interface changes very likely to change binary compatibility.

The second approach means that the structure can be an incomplete type, opaque to the user so the user doesn't see the interals of the implementation. Binary compatibility is far easier to maintain, but it can imply extra indirection and memory allocations in some situations over what might be possible if the user can control allocation of the structure.


There isn't going to be a clear winner. Each has advantages and disadvantages, and which one you should prefer would depend on the circumstances.

With the caller-allocated approach, the caller gets more flexibility. The caller can choose to allocate the struct on the stack or can choose to use a different allocator. A disadvantage--particularly from the perspective of the called library--is that the struct is not opaque. If the caller is responsible for allocation, the caller must know how big the struct is. This might not be desirable if the library author wishes to have more freedom for changing the struct's internals.


From my experience, I recommend the following way:

struct foo *p = foo_init();
foo_destroy(p);

especially when "struct foo" is complex and has members with dynamic memory. For small "struct foo", this way costs extra few bytes for a pointer; then the pthread way is preferred. Note that pthread_mutex_t has 24 bytes on 32-bit system, relatively small.


The first API, because you can allocate memory for the struct from either stack or heap. In the second API, dynamic allocation must be used and you are cannot control the way memory is allocated for the struct.


Win32 often uses a third approach: caller creates the structures and initializes fields manually, including a 'size' parameter which acts as version and also to place variable-length members - strings typically - in the structure rather than in a separate memory allocation.


There isn't necessarily any difference between the two, but the latter tends to produce a more abstract interface that gives the user more simplicity and the implementer more flexibility.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜