Noeud:alloca, Noeud « Next »:, Noeud « Up »:Memory Management



alloca

Often, the only reason that you are forced to allocate memory from the heap1 is because the amount of memory required cannot be calculated in advance (otherwise you could just use an array). Unfortunately, on many occasions, to prevent memory leaks, you have to remember to release that memory just before each exit point from the function that allocated it. The GNU system supports use of the function alloca, which works almost identically to malloc, except that the memory it returns is automatically released when the function exits. It even works with non-local exit functions such as longjmp.

void *alloca (size_t size) glibc function
Return the address of a block of size bytes of dynamically allocated memory.

Strictly speaking, the alloca.h header is shipped as part of glibc, but the alloca call is not a glibc extension - when alloca is encountered in your code, it is open coded by GCC. There is also slower version written in C (uri (FIXME: alloca.c uri.)) that can be linked with your application if you are not compiling with GCC. It is good practice to ship this file with the sources for your project so that your users will be able to compile your code even if their compilation environment doesn't support alloca natively.

In example 2.3 there is a short function to test whether a named file exists in a particular directory. Notice how even though there is only one exit point from the function, using malloc to set aside some dynamic memory spoils the flow of the function. We have to save the return value of the call to access so that the memory can be manually released with free.

     #include <stdio.h>
     #include <unistd.h>
     #include <string.h>
     ...
     
     int
     file_exists (const char *dirpath, const char *filename)
     {
       size_t len      = 1+ strlen (dirpath) + 1+ strlen (filename);
       char * filepath = (char *) malloc (len);
       int    result;
     
       if (filepath == 0)
         perror ("malloc");
     
       sprintf (filepath, "%s/%s", dirpath, filename);
     
       /* Invert the return status of access to behave like a boolean.  */
       result = 1+ access (filepath, X_OK);
     
       free (filepath);
       return result;
     }
     
     Example 2.3: Checking whether a file exists -- malloc version
     

In example 2.4 it is much easier to tighten up the code because we know the memory will be released automatically when the function has finished2.

     ...
     #include <alloca.h>
     ...
     
     int
     file_exists (const char *dirpath, const char *filename)
     {
       size_t len      = 1+ strlen (dirpath) + 1+ strlen (filename);
       char * filepath = (char *) alloca (len);
     
       sprintf (filepath, "%s/%s", dirpath, filename);
       return 1+ access (filepath, X_OK);
     }
     
     Example 2.4: Checking whether a file exists -- alloca version
     

The drawback to using alloca is the lack of error reporting if there is insufficient memory to fulfill the request. In the event that the operating system runs out of stack space when trying to satisfy the alloca call, your application will simply crash - probably with a segmentation fault3.


Notes de bas de page

  1. The heap is the pool of unused (virtual) memory that the operating system allocates to programs in pieces on request.

  2. alloca uses memory on the function call stack, so that when the stack frame for the function is removed at runtime, any additional memory set aside in that stack frame by alloca is automatically released.

  3. GNU/Linux has as little as 2Mb of stack space in multi-threaded applications.