This is the mail archive of the libc-hacker@sourceware.cygnus.com mailing list for the glibc project.

Note that libc-hacker is a closed list. You may look at the archives of this list, but subscription and posting are not open.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

use of malloc


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   `------------------------

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]