use of malloc
Ulrich Drepper
drepper@redhat.com
Fri Apr 21 10:39:00 GMT 2000
While I added __builtin_expect in a few more places I was especially
looking at memory allocation code since, as explained in the last
mail, the error checking for the memory allocation functions is a
perfect candidate for the use of __builtin_expect.
Then I stumbled accross the NIS code which contains a lot of bugs. I
don't want to pick on this too much but I'm pretty sure I haven't made
these mistakes in the code I wrote. What I want to achieve is that
everybody goes again over the code he wrote and looks for the folling
bugs and optimization possibilities. I've made a fre minutes ago some
changes to one file in the NIS code which might serve as a guideline.
Please follow the guidelines below:
- *always* check the result of the memory allocation functions. These
are not only malloc, calloc, realloc, etc but also strdup, asprintf,
and all the others doing implicit allocations.
- make sure you free all the memory allocated in the error case. This
might get ugly but, as in the NIS file I corrected, you can use goto
for this. This is a legitemate use of goto.
- in general, make sure no memory is leaked. I'm pretty sure I got most
of the code I'm using on my system (i.e., no NIS) leak free using the
tools we have already in glibc. Please use them in your environments
as well.
I'll improve the tool a bit sometime soon so it'll be easier to use but
it's already usable.
- optimize the user of malloc/calloc. Often a struct and its content
have to be allocated at the same time. The easiest way if to do it
on two steps with two allocations. But if the information has the
same lifetime this is a waste. The malloc and especially the free
function is pretty slow.
A better way is to allocate enough space in the block to have room
for the struct and the data. Example (without error checking):
struct test_struct *sp = malloc (sizeof (struct test_struct));
sp->data = malloc (nent * sizeof (int));
This can be written better as
struct test_struct *sp = malloc (sizeof (struct test_struct)
+ nent * sizeof (int));
sp->data = (int *) (sp + 1);
The advantages should be obvious:
+ one malloc call
+ therefore, one free call
+ therefore, simpler error case handling
The above can be done for as many different pieces as you want.
Throughout glibc you'll find numerous examples of code where I use this.
The only thing you have to be careful about is alignment.
- use __builtin_expect for the error case. This is the perfect use for
__builtin_expect since we never want to optimize for this case. It's
always the exception.
--
---------------. drepper at gnu.org ,-. 1325 Chesapeake Terrace
Ulrich Drepper \ ,-------------------' \ Sunnyvale, CA 94089 USA
Red Hat `--' drepper at redhat.com `------------------------
More information about the Libc-hacker
mailing list