Paul Eggert <egg...@cs.ucla.edu> writes: > +struct allocator > +{ > + /* Call MALLOC to allocate memory, like 'malloc'. On failure MALLOC > + should return NULL, though not necessarily set errno. When given > + a zero size it may return NULL even if successful. */ > + void *(*malloc) (size_t); > + > + /* If nonnull, call REALLOC to reallocate memory, like 'realloc'. > + On failure REALLOC should return NULL, though not necessarily set > + errno. When given a zero size it may return NULL even if > + successful. */ > + void *(*realloc) (void *, size_t); > + > + /* Call FREE to free memory, like 'free'. */ > + void (*free) (void *); > + > + /* If nonnull, call DIE if MALLOC or REALLOC fails. DIE should > + not return. */ > + void (*die) (void); > +};
It might be a good idea to mark each function with appropriate GCC attributes, e.g. __attribute__((malloc)) for malloc and realloc and __attribute__((noreturn)) for die. I was a little surprised to see the first proposed use of this actually copy out all of the pointers into local variables. If that's the way it's going to be used, I guess that would make the attributes useless, unless they were applied to the local variables too. I'm not sure why die is a separate member. Couldn't xmalloc and xrealloc simply be used as the malloc and realloc functions? I would have guessed that there would be a global instance of this allocator, something like: struct allocator standard_allocator = { malloc, realloc, free, NULL }; and possibly another one that uses the x* functions: struct allocator xstandard_allocator = { xmalloc, xrealloc, free, NULL }; or struct allocator xstandard_allocator = { malloc, realloc, free, xalloc_die }; With global instances, functions can pass in one of those instead of a null allocator, and then the functions that call into the allocator don't have to have special cases. -- Ben Pfaff http://benpfaff.org