diff options
Diffstat (limited to 'manual/memory.texi')
-rw-r--r-- | manual/memory.texi | 3504 |
1 files changed, 0 insertions, 3504 deletions
diff --git a/manual/memory.texi b/manual/memory.texi deleted file mode 100644 index fb6b594ef1..0000000000 --- a/manual/memory.texi +++ /dev/null @@ -1,3504 +0,0 @@ -@node Memory, Character Handling, Error Reporting, Top -@chapter Virtual Memory Allocation And Paging -@c %MENU% Allocating virtual memory and controlling paging -@cindex memory allocation -@cindex storage allocation - -This chapter describes how processes manage and use memory in a system -that uses @theglibc{}. - -@Theglibc{} has several functions for dynamically allocating -virtual memory in various ways. They vary in generality and in -efficiency. The library also provides functions for controlling paging -and allocation of real memory. - - -@menu -* Memory Concepts:: An introduction to concepts and terminology. -* Memory Allocation:: Allocating storage for your program data -* Resizing the Data Segment:: @code{brk}, @code{sbrk} -* Locking Pages:: Preventing page faults -@end menu - -Memory mapped I/O is not discussed in this chapter. @xref{Memory-mapped I/O}. - - - -@node Memory Concepts -@section Process Memory Concepts - -One of the most basic resources a process has available to it is memory. -There are a lot of different ways systems organize memory, but in a -typical one, each process has one linear virtual address space, with -addresses running from zero to some huge maximum. It need not be -contiguous; i.e., not all of these addresses actually can be used to -store data. - -The virtual memory is divided into pages (4 kilobytes is typical). -Backing each page of virtual memory is a page of real memory (called a -@dfn{frame}) or some secondary storage, usually disk space. The disk -space might be swap space or just some ordinary disk file. Actually, a -page of all zeroes sometimes has nothing at all backing it -- there's -just a flag saying it is all zeroes. -@cindex page frame -@cindex frame, real memory -@cindex swap space -@cindex page, virtual memory - -The same frame of real memory or backing store can back multiple virtual -pages belonging to multiple processes. This is normally the case, for -example, with virtual memory occupied by @glibcadj{} code. The same -real memory frame containing the @code{printf} function backs a virtual -memory page in each of the existing processes that has a @code{printf} -call in its program. - -In order for a program to access any part of a virtual page, the page -must at that moment be backed by (``connected to'') a real frame. But -because there is usually a lot more virtual memory than real memory, the -pages must move back and forth between real memory and backing store -regularly, coming into real memory when a process needs to access them -and then retreating to backing store when not needed anymore. This -movement is called @dfn{paging}. - -When a program attempts to access a page which is not at that moment -backed by real memory, this is known as a @dfn{page fault}. When a page -fault occurs, the kernel suspends the process, places the page into a -real page frame (this is called ``paging in'' or ``faulting in''), then -resumes the process so that from the process' point of view, the page -was in real memory all along. In fact, to the process, all pages always -seem to be in real memory. Except for one thing: the elapsed execution -time of an instruction that would normally be a few nanoseconds is -suddenly much, much, longer (because the kernel normally has to do I/O -to complete the page-in). For programs sensitive to that, the functions -described in @ref{Locking Pages} can control it. -@cindex page fault -@cindex paging - -Within each virtual address space, a process has to keep track of what -is at which addresses, and that process is called memory allocation. -Allocation usually brings to mind meting out scarce resources, but in -the case of virtual memory, that's not a major goal, because there is -generally much more of it than anyone needs. Memory allocation within a -process is mainly just a matter of making sure that the same byte of -memory isn't used to store two different things. - -Processes allocate memory in two major ways: by exec and -programmatically. Actually, forking is a third way, but it's not very -interesting. @xref{Creating a Process}. - -Exec is the operation of creating a virtual address space for a process, -loading its basic program into it, and executing the program. It is -done by the ``exec'' family of functions (e.g. @code{execl}). The -operation takes a program file (an executable), it allocates space to -load all the data in the executable, loads it, and transfers control to -it. That data is most notably the instructions of the program (the -@dfn{text}), but also literals and constants in the program and even -some variables: C variables with the static storage class (@pxref{Memory -Allocation and C}). -@cindex executable -@cindex literals -@cindex constants - -Once that program begins to execute, it uses programmatic allocation to -gain additional memory. In a C program with @theglibc{}, there -are two kinds of programmatic allocation: automatic and dynamic. -@xref{Memory Allocation and C}. - -Memory-mapped I/O is another form of dynamic virtual memory allocation. -Mapping memory to a file means declaring that the contents of certain -range of a process' addresses shall be identical to the contents of a -specified regular file. The system makes the virtual memory initially -contain the contents of the file, and if you modify the memory, the -system writes the same modification to the file. Note that due to the -magic of virtual memory and page faults, there is no reason for the -system to do I/O to read the file, or allocate real memory for its -contents, until the program accesses the virtual memory. -@xref{Memory-mapped I/O}. -@cindex memory mapped I/O -@cindex memory mapped file -@cindex files, accessing - -Just as it programmatically allocates memory, the program can -programmatically deallocate (@dfn{free}) it. You can't free the memory -that was allocated by exec. When the program exits or execs, you might -say that all its memory gets freed, but since in both cases the address -space ceases to exist, the point is really moot. @xref{Program -Termination}. -@cindex execing a program -@cindex freeing memory -@cindex exiting a program - -A process' virtual address space is divided into segments. A segment is -a contiguous range of virtual addresses. Three important segments are: - -@itemize @bullet - -@item - -The @dfn{text segment} contains a program's instructions and literals and -static constants. It is allocated by exec and stays the same size for -the life of the virtual address space. - -@item -The @dfn{data segment} is working storage for the program. It can be -preallocated and preloaded by exec and the process can extend or shrink -it by calling functions as described in @xref{Resizing the Data -Segment}. Its lower end is fixed. - -@item -The @dfn{stack segment} contains a program stack. It grows as the stack -grows, but doesn't shrink when the stack shrinks. - -@end itemize - - - -@node Memory Allocation -@section Allocating Storage For Program Data - -This section covers how ordinary programs manage storage for their data, -including the famous @code{malloc} function and some fancier facilities -special to @theglibc{} and GNU Compiler. - -@menu -* Memory Allocation and C:: How to get different kinds of allocation in C. -* The GNU Allocator:: An overview of the GNU @code{malloc} - implementation. -* Unconstrained Allocation:: The @code{malloc} facility allows fully general - dynamic allocation. -* Allocation Debugging:: Finding memory leaks and not freed memory. -* Replacing malloc:: Using your own @code{malloc}-style allocator. -* Obstacks:: Obstacks are less general than malloc - but more efficient and convenient. -* Variable Size Automatic:: Allocation of variable-sized blocks - of automatic storage that are freed when the - calling function returns. -@end menu - - -@node Memory Allocation and C -@subsection Memory Allocation in C Programs - -The C language supports two kinds of memory allocation through the -variables in C programs: - -@itemize @bullet -@item -@dfn{Static allocation} is what happens when you declare a static or -global variable. Each static or global variable defines one block of -space, of a fixed size. The space is allocated once, when your program -is started (part of the exec operation), and is never freed. -@cindex static memory allocation -@cindex static storage class - -@item -@dfn{Automatic allocation} happens when you declare an automatic -variable, such as a function argument or a local variable. The space -for an automatic variable is allocated when the compound statement -containing the declaration is entered, and is freed when that -compound statement is exited. -@cindex automatic memory allocation -@cindex automatic storage class - -In GNU C, the size of the automatic storage can be an expression -that varies. In other C implementations, it must be a constant. -@end itemize - -A third important kind of memory allocation, @dfn{dynamic allocation}, -is not supported by C variables but is available via @glibcadj{} -functions. -@cindex dynamic memory allocation - -@subsubsection Dynamic Memory Allocation -@cindex dynamic memory allocation - -@dfn{Dynamic memory allocation} is a technique in which programs -determine as they are running where to store some information. You need -dynamic allocation when the amount of memory you need, or how long you -continue to need it, depends on factors that are not known before the -program runs. - -For example, you may need a block to store a line read from an input -file; since there is no limit to how long a line can be, you must -allocate the memory dynamically and make it dynamically larger as you -read more of the line. - -Or, you may need a block for each record or each definition in the input -data; since you can't know in advance how many there will be, you must -allocate a new block for each record or definition as you read it. - -When you use dynamic allocation, the allocation of a block of memory is -an action that the program requests explicitly. You call a function or -macro when you want to allocate space, and specify the size with an -argument. If you want to free the space, you do so by calling another -function or macro. You can do these things whenever you want, as often -as you want. - -Dynamic allocation is not supported by C variables; there is no storage -class ``dynamic'', and there can never be a C variable whose value is -stored in dynamically allocated space. The only way to get dynamically -allocated memory is via a system call (which is generally via a @glibcadj{} -function call), and the only way to refer to dynamically -allocated space is through a pointer. Because it is less convenient, -and because the actual process of dynamic allocation requires more -computation time, programmers generally use dynamic allocation only when -neither static nor automatic allocation will serve. - -For example, if you want to allocate dynamically some space to hold a -@code{struct foobar}, you cannot declare a variable of type @code{struct -foobar} whose contents are the dynamically allocated space. But you can -declare a variable of pointer type @code{struct foobar *} and assign it the -address of the space. Then you can use the operators @samp{*} and -@samp{->} on this pointer variable to refer to the contents of the space: - -@smallexample -@{ - struct foobar *ptr - = (struct foobar *) malloc (sizeof (struct foobar)); - ptr->name = x; - ptr->next = current_foobar; - current_foobar = ptr; -@} -@end smallexample - -@node The GNU Allocator -@subsection The GNU Allocator -@cindex gnu allocator - -The @code{malloc} implementation in @theglibc{} is derived from ptmalloc -(pthreads malloc), which in turn is derived from dlmalloc (Doug Lea malloc). -This malloc may allocate memory in two different ways depending on their size -and certain parameters that may be controlled by users. The most common way is -to allocate portions of memory (called chunks) from a large contiguous area of -memory and manage these areas to optimize their use and reduce wastage in the -form of unusable chunks. Traditionally the system heap was set up to be the one -large memory area but the @glibcadj{} @code{malloc} implementation maintains -multiple such areas to optimize their use in multi-threaded applications. Each -such area is internally referred to as an @dfn{arena}. - -As opposed to other versions, the @code{malloc} in @theglibc{} does not round -up chunk sizes to powers of two, neither for large nor for small sizes. -Neighboring chunks can be coalesced on a @code{free} no matter what their size -is. This makes the implementation suitable for all kinds of allocation -patterns without generally incurring high memory waste through fragmentation. -The presence of multiple arenas allows multiple threads to allocate -memory simultaneously in separate arenas, thus improving performance. - -The other way of memory allocation is for very large blocks, i.e. much larger -than a page. These requests are allocated with @code{mmap} (anonymous or via -@file{/dev/zero}; @pxref{Memory-mapped I/O})). This has the great advantage -that these chunks are returned to the system immediately when they are freed. -Therefore, it cannot happen that a large chunk becomes ``locked'' in between -smaller ones and even after calling @code{free} wastes memory. The size -threshold for @code{mmap} to be used is dynamic and gets adjusted according to -allocation patterns of the program. @code{mallopt} can be used to statically -adjust the threshold using @code{M_MMAP_THRESHOLD} and the use of @code{mmap} -can be disabled completely with @code{M_MMAP_MAX}; -@pxref{Malloc Tunable Parameters}. - -A more detailed technical description of the GNU Allocator is maintained in -the @glibcadj{} wiki. See -@uref{https://sourceware.org/glibc/wiki/MallocInternals}. - -It is possible to use your own custom @code{malloc} instead of the -built-in allocator provided by @theglibc{}. @xref{Replacing malloc}. - -@node Unconstrained Allocation -@subsection Unconstrained Allocation -@cindex unconstrained memory allocation -@cindex @code{malloc} function -@cindex heap, dynamic allocation from - -The most general dynamic allocation facility is @code{malloc}. It -allows you to allocate blocks of memory of any size at any time, make -them bigger or smaller at any time, and free the blocks individually at -any time (or never). - -@menu -* Basic Allocation:: Simple use of @code{malloc}. -* Malloc Examples:: Examples of @code{malloc}. @code{xmalloc}. -* Freeing after Malloc:: Use @code{free} to free a block you - got with @code{malloc}. -* Changing Block Size:: Use @code{realloc} to make a block - bigger or smaller. -* Allocating Cleared Space:: Use @code{calloc} to allocate a - block and clear it. -* Aligned Memory Blocks:: Allocating specially aligned memory. -* Malloc Tunable Parameters:: Use @code{mallopt} to adjust allocation - parameters. -* Heap Consistency Checking:: Automatic checking for errors. -* Hooks for Malloc:: You can use these hooks for debugging - programs that use @code{malloc}. -* Statistics of Malloc:: Getting information about how much - memory your program is using. -* Summary of Malloc:: Summary of @code{malloc} and related functions. -@end menu - -@node Basic Allocation -@subsubsection Basic Memory Allocation -@cindex allocation of memory with @code{malloc} - -To allocate a block of memory, call @code{malloc}. The prototype for -this function is in @file{stdlib.h}. -@pindex stdlib.h - -@comment malloc.h stdlib.h -@comment ISO -@deftypefun {void *} malloc (size_t @var{size}) -@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{} @acsfd{} @acsmem{}}} -@c Malloc hooks and __morecore pointers, as well as such parameters as -@c max_n_mmaps and max_mmapped_mem, are accessed without guards, so they -@c could pose a thread safety issue; in order to not declare malloc -@c MT-unsafe, it's modifying the hooks and parameters while multiple -@c threads are active that is regarded as unsafe. An arena's next field -@c is initialized and never changed again, except for main_arena's, -@c that's protected by list_lock; next_free is only modified while -@c list_lock is held too. All other data members of an arena, as well -@c as the metadata of the memory areas assigned to it, are only modified -@c while holding the arena's mutex (fastbin pointers use catomic ops -@c because they may be modified by free without taking the arena's -@c lock). Some reassurance was needed for fastbins, for it wasn't clear -@c how they were initialized. It turns out they are always -@c zero-initialized: main_arena's, for being static data, and other -@c arena's, for being just-mmapped memory. - -@c Leaking file descriptors and memory in case of cancellation is -@c unavoidable without disabling cancellation, but the lock situation is -@c a bit more complicated: we don't have fallback arenas for malloc to -@c be safe to call from within signal handlers. Error-checking mutexes -@c or trylock could enable us to try and use alternate arenas, even with -@c -DPER_THREAD (enabled by default), but supporting interruption -@c (cancellation or signal handling) while holding the arena list mutex -@c would require more work; maybe blocking signals and disabling async -@c cancellation while manipulating the arena lists? - -@c __libc_malloc @asulock @aculock @acsfd @acsmem -@c force_reg ok -@c *malloc_hook unguarded -@c arena_lock @asulock @aculock @acsfd @acsmem -@c mutex_lock @asulock @aculock -@c arena_get2 @asulock @aculock @acsfd @acsmem -@c get_free_list @asulock @aculock -@c mutex_lock (list_lock) dup @asulock @aculock -@c mutex_unlock (list_lock) dup @aculock -@c mutex_lock (arena lock) dup @asulock @aculock [returns locked] -@c __get_nprocs ext ok @acsfd -@c NARENAS_FROM_NCORES ok -@c catomic_compare_and_exchange_bool_acq ok -@c _int_new_arena ok @asulock @aculock @acsmem -@c new_heap ok @acsmem -@c mmap ok @acsmem -@c munmap ok @acsmem -@c mprotect ok -@c chunk2mem ok -@c set_head ok -@c tsd_setspecific dup ok -@c mutex_init ok -@c mutex_lock (just-created mutex) ok, returns locked -@c mutex_lock (list_lock) dup @asulock @aculock -@c atomic_write_barrier ok -@c mutex_unlock (list_lock) @aculock -@c catomic_decrement ok -@c reused_arena @asulock @aculock -@c reads&writes next_to_use and iterates over arena next without guards -@c those are harmless as long as we don't drop arenas from the -@c NEXT list, and we never do; when a thread terminates, -@c arena_thread_freeres prepends the arena to the free_list -@c NEXT_FREE list, but NEXT is never modified, so it's safe! -@c mutex_trylock (arena lock) @asulock @aculock -@c mutex_lock (arena lock) dup @asulock @aculock -@c tsd_setspecific dup ok -@c _int_malloc @acsfd @acsmem -@c checked_request2size ok -@c REQUEST_OUT_OF_RANGE ok -@c request2size ok -@c get_max_fast ok -@c fastbin_index ok -@c fastbin ok -@c catomic_compare_and_exhange_val_acq ok -@c malloc_printerr dup @mtsenv -@c if we get to it, we're toast already, undefined behavior must have -@c been invoked before -@c libc_message @mtsenv [no leaks with cancellation disabled] -@c FATAL_PREPARE ok -@c pthread_setcancelstate disable ok -@c libc_secure_getenv @mtsenv -@c getenv @mtsenv -@c open_not_cancel_2 dup @acsfd -@c strchrnul ok -@c WRITEV_FOR_FATAL ok -@c writev ok -@c mmap ok @acsmem -@c munmap ok @acsmem -@c BEFORE_ABORT @acsfd -@c backtrace ok -@c write_not_cancel dup ok -@c backtrace_symbols_fd @aculock -@c open_not_cancel_2 dup @acsfd -@c read_not_cancel dup ok -@c close_not_cancel_no_status dup @acsfd -@c abort ok -@c itoa_word ok -@c abort ok -@c check_remalloced_chunk ok/disabled -@c chunk2mem dup ok -@c alloc_perturb ok -@c in_smallbin_range ok -@c smallbin_index ok -@c bin_at ok -@c last ok -@c malloc_consolidate ok -@c get_max_fast dup ok -@c clear_fastchunks ok -@c unsorted_chunks dup ok -@c fastbin dup ok -@c atomic_exchange_acq ok -@c check_inuse_chunk dup ok/disabled -@c chunk_at_offset dup ok -@c chunksize dup ok -@c inuse_bit_at_offset dup ok -@c unlink dup ok -@c clear_inuse_bit_at_offset dup ok -@c in_smallbin_range dup ok -@c set_head dup ok -@c malloc_init_state ok -@c bin_at dup ok -@c set_noncontiguous dup ok -@c set_max_fast dup ok -@c initial_top ok -@c unsorted_chunks dup ok -@c check_malloc_state ok/disabled -@c set_inuse_bit_at_offset ok -@c check_malloced_chunk ok/disabled -@c largebin_index ok -@c have_fastchunks ok -@c unsorted_chunks ok -@c bin_at ok -@c chunksize ok -@c chunk_at_offset ok -@c set_head ok -@c set_foot ok -@c mark_bin ok -@c idx2bit ok -@c first ok -@c unlink ok -@c malloc_printerr dup ok -@c in_smallbin_range dup ok -@c idx2block ok -@c idx2bit dup ok -@c next_bin ok -@c sysmalloc @acsfd @acsmem -@c MMAP @acsmem -@c set_head dup ok -@c check_chunk ok/disabled -@c chunk2mem dup ok -@c chunksize dup ok -@c chunk_at_offset dup ok -@c heap_for_ptr ok -@c grow_heap ok -@c mprotect ok -@c set_head dup ok -@c new_heap @acsmem -@c MMAP dup @acsmem -@c munmap @acsmem -@c top ok -@c set_foot dup ok -@c contiguous ok -@c MORECORE ok -@c *__morecore ok unguarded -@c __default_morecore -@c sbrk ok -@c force_reg dup ok -@c *__after_morecore_hook unguarded -@c set_noncontiguous ok -@c malloc_printerr dup ok -@c _int_free (have_lock) @acsfd @acsmem [@asulock @aculock] -@c chunksize dup ok -@c mutex_unlock dup @aculock/!have_lock -@c malloc_printerr dup ok -@c check_inuse_chunk ok/disabled -@c chunk_at_offset dup ok -@c mutex_lock dup @asulock @aculock/@have_lock -@c chunk2mem dup ok -@c free_perturb ok -@c set_fastchunks ok -@c catomic_and ok -@c fastbin_index dup ok -@c fastbin dup ok -@c catomic_compare_and_exchange_val_rel ok -@c chunk_is_mmapped ok -@c contiguous dup ok -@c prev_inuse ok -@c unlink dup ok -@c inuse_bit_at_offset dup ok -@c clear_inuse_bit_at_offset ok -@c unsorted_chunks dup ok -@c in_smallbin_range dup ok -@c set_head dup ok -@c set_foot dup ok -@c check_free_chunk ok/disabled -@c check_chunk dup ok/disabled -@c have_fastchunks dup ok -@c malloc_consolidate dup ok -@c systrim ok -@c MORECORE dup ok -@c *__after_morecore_hook dup unguarded -@c set_head dup ok -@c check_malloc_state ok/disabled -@c top dup ok -@c heap_for_ptr dup ok -@c heap_trim @acsfd @acsmem -@c top dup ok -@c chunk_at_offset dup ok -@c prev_chunk ok -@c chunksize dup ok -@c prev_inuse dup ok -@c delete_heap @acsmem -@c munmap dup @acsmem -@c unlink dup ok -@c set_head dup ok -@c shrink_heap @acsfd -@c check_may_shrink_heap @acsfd -@c open_not_cancel_2 @acsfd -@c read_not_cancel ok -@c close_not_cancel_no_status @acsfd -@c MMAP dup ok -@c madvise ok -@c munmap_chunk @acsmem -@c chunksize dup ok -@c chunk_is_mmapped dup ok -@c chunk2mem dup ok -@c malloc_printerr dup ok -@c munmap dup @acsmem -@c check_malloc_state ok/disabled -@c arena_get_retry @asulock @aculock @acsfd @acsmem -@c mutex_unlock dup @aculock -@c mutex_lock dup @asulock @aculock -@c arena_get2 dup @asulock @aculock @acsfd @acsmem -@c mutex_unlock @aculock -@c mem2chunk ok -@c chunk_is_mmapped ok -@c arena_for_chunk ok -@c chunk_non_main_arena ok -@c heap_for_ptr ok -This function returns a pointer to a newly allocated block @var{size} -bytes long, or a null pointer if the block could not be allocated. -@end deftypefun - -The contents of the block are undefined; you must initialize it yourself -(or use @code{calloc} instead; @pxref{Allocating Cleared Space}). -Normally you would cast the value as a pointer to the kind of object -that you want to store in the block. Here we show an example of doing -so, and of initializing the space with zeros using the library function -@code{memset} (@pxref{Copying Strings and Arrays}): - -@smallexample -struct foo *ptr; -@dots{} -ptr = (struct foo *) malloc (sizeof (struct foo)); -if (ptr == 0) abort (); -memset (ptr, 0, sizeof (struct foo)); -@end smallexample - -You can store the result of @code{malloc} into any pointer variable -without a cast, because @w{ISO C} automatically converts the type -@code{void *} to another type of pointer when necessary. But the cast -is necessary in contexts other than assignment operators or if you might -want your code to run in traditional C. - -Remember that when allocating space for a string, the argument to -@code{malloc} must be one plus the length of the string. This is -because a string is terminated with a null character that doesn't count -in the ``length'' of the string but does need space. For example: - -@smallexample -char *ptr; -@dots{} -ptr = (char *) malloc (length + 1); -@end smallexample - -@noindent -@xref{Representation of Strings}, for more information about this. - -@node Malloc Examples -@subsubsection Examples of @code{malloc} - -If no more space is available, @code{malloc} returns a null pointer. -You should check the value of @emph{every} call to @code{malloc}. It is -useful to write a subroutine that calls @code{malloc} and reports an -error if the value is a null pointer, returning only if the value is -nonzero. This function is conventionally called @code{xmalloc}. Here -it is: - -@smallexample -void * -xmalloc (size_t size) -@{ - void *value = malloc (size); - if (value == 0) - fatal ("virtual memory exhausted"); - return value; -@} -@end smallexample - -Here is a real example of using @code{malloc} (by way of @code{xmalloc}). -The function @code{savestring} will copy a sequence of characters into -a newly allocated null-terminated string: - -@smallexample -@group -char * -savestring (const char *ptr, size_t len) -@{ - char *value = (char *) xmalloc (len + 1); - value[len] = '\0'; - return (char *) memcpy (value, ptr, len); -@} -@end group -@end smallexample - -The block that @code{malloc} gives you is guaranteed to be aligned so -that it can hold any type of data. On @gnusystems{}, the address is -always a multiple of eight on 32-bit systems, and a multiple of 16 on -64-bit systems. Only rarely is any higher boundary (such as a page -boundary) necessary; for those cases, use @code{aligned_alloc} or -@code{posix_memalign} (@pxref{Aligned Memory Blocks}). - -Note that the memory located after the end of the block is likely to be -in use for something else; perhaps a block already allocated by another -call to @code{malloc}. If you attempt to treat the block as longer than -you asked for it to be, you are liable to destroy the data that -@code{malloc} uses to keep track of its blocks, or you may destroy the -contents of another block. If you have already allocated a block and -discover you want it to be bigger, use @code{realloc} (@pxref{Changing -Block Size}). - -@node Freeing after Malloc -@subsubsection Freeing Memory Allocated with @code{malloc} -@cindex freeing memory allocated with @code{malloc} -@cindex heap, freeing memory from - -When you no longer need a block that you got with @code{malloc}, use the -function @code{free} to make the block available to be allocated again. -The prototype for this function is in @file{stdlib.h}. -@pindex stdlib.h - -@comment malloc.h stdlib.h -@comment ISO -@deftypefun void free (void *@var{ptr}) -@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{} @acsfd{} @acsmem{}}} -@c __libc_free @asulock @aculock @acsfd @acsmem -@c releasing memory into fastbins modifies the arena without taking -@c its mutex, but catomic operations ensure safety. If two (or more) -@c threads are running malloc and have their own arenas locked when -@c each gets a signal whose handler free()s large (non-fastbin-able) -@c blocks from each other's arena, we deadlock; this is a more general -@c case of @asulock. -@c *__free_hook unguarded -@c mem2chunk ok -@c chunk_is_mmapped ok, chunk bits not modified after allocation -@c chunksize ok -@c munmap_chunk dup @acsmem -@c arena_for_chunk dup ok -@c _int_free (!have_lock) dup @asulock @aculock @acsfd @acsmem -The @code{free} function deallocates the block of memory pointed at -by @var{ptr}. -@end deftypefun - -Freeing a block alters the contents of the block. @strong{Do not expect to -find any data (such as a pointer to the next block in a chain of blocks) in -the block after freeing it.} Copy whatever you need out of the block before -freeing it! Here is an example of the proper way to free all the blocks in -a chain, and the strings that they point to: - -@smallexample -struct chain - @{ - struct chain *next; - char *name; - @} - -void -free_chain (struct chain *chain) -@{ - while (chain != 0) - @{ - struct chain *next = chain->next; - free (chain->name); - free (chain); - chain = next; - @} -@} -@end smallexample - -Occasionally, @code{free} can actually return memory to the operating -system and make the process smaller. Usually, all it can do is allow a -later call to @code{malloc} to reuse the space. In the meantime, the -space remains in your program as part of a free-list used internally by -@code{malloc}. - -There is no point in freeing blocks at the end of a program, because all -of the program's space is given back to the system when the process -terminates. - -@node Changing Block Size -@subsubsection Changing the Size of a Block -@cindex changing the size of a block (@code{malloc}) - -Often you do not know for certain how big a block you will ultimately need -at the time you must begin to use the block. For example, the block might -be a buffer that you use to hold a line being read from a file; no matter -how long you make the buffer initially, you may encounter a line that is -longer. - -You can make the block longer by calling @code{realloc} or -@code{reallocarray}. These functions are declared in @file{stdlib.h}. -@pindex stdlib.h - -@comment malloc.h stdlib.h -@comment ISO -@deftypefun {void *} realloc (void *@var{ptr}, size_t @var{newsize}) -@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{} @acsfd{} @acsmem{}}} -@c It may call the implementations of malloc and free, so all of their -@c issues arise, plus the realloc hook, also accessed without guards. - -@c __libc_realloc @asulock @aculock @acsfd @acsmem -@c *__realloc_hook unguarded -@c __libc_free dup @asulock @aculock @acsfd @acsmem -@c __libc_malloc dup @asulock @aculock @acsfd @acsmem -@c mem2chunk dup ok -@c chunksize dup ok -@c malloc_printerr dup ok -@c checked_request2size dup ok -@c chunk_is_mmapped dup ok -@c mremap_chunk -@c chunksize dup ok -@c __mremap ok -@c set_head dup ok -@c MALLOC_COPY ok -@c memcpy ok -@c munmap_chunk dup @acsmem -@c arena_for_chunk dup ok -@c mutex_lock (arena mutex) dup @asulock @aculock -@c _int_realloc @acsfd @acsmem -@c malloc_printerr dup ok -@c check_inuse_chunk dup ok/disabled -@c chunk_at_offset dup ok -@c chunksize dup ok -@c set_head_size dup ok -@c chunk_at_offset dup ok -@c set_head dup ok -@c chunk2mem dup ok -@c inuse dup ok -@c unlink dup ok -@c _int_malloc dup @acsfd @acsmem -@c mem2chunk dup ok -@c MALLOC_COPY dup ok -@c _int_free (have_lock) dup @acsfd @acsmem -@c set_inuse_bit_at_offset dup ok -@c set_head dup ok -@c mutex_unlock (arena mutex) dup @aculock -@c _int_free (!have_lock) dup @asulock @aculock @acsfd @acsmem - -The @code{realloc} function changes the size of the block whose address is -@var{ptr} to be @var{newsize}. - -Since the space after the end of the block may be in use, @code{realloc} -may find it necessary to copy the block to a new address where more free -space is available. The value of @code{realloc} is the new address of the -block. If the block needs to be moved, @code{realloc} copies the old -contents. - -If you pass a null pointer for @var{ptr}, @code{realloc} behaves just -like @samp{malloc (@var{newsize})}. This can be convenient, but beware -that older implementations (before @w{ISO C}) may not support this -behavior, and will probably crash when @code{realloc} is passed a null -pointer. -@end deftypefun - -@comment malloc.h stdlib.h -@comment BSD -@deftypefun {void *} reallocarray (void *@var{ptr}, size_t @var{nmemb}, size_t @var{size}) -@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{} @acsfd{} @acsmem{}}} - -The @code{reallocarray} function changes the size of the block whose address -is @var{ptr} to be long enough to contain a vector of @var{nmemb} elements, -each of size @var{size}. It is equivalent to @samp{realloc (@var{ptr}, -@var{nmemb} * @var{size})}, except that @code{reallocarray} fails safely if -the multiplication overflows, by setting @code{errno} to @code{ENOMEM}, -returning a null pointer, and leaving the original block unchanged. - -@code{reallocarray} should be used instead of @code{realloc} when the new size -of the allocated block is the result of a multiplication that might overflow. - -@strong{Portability Note:} This function is not part of any standard. It was -first introduced in OpenBSD 5.6. -@end deftypefun - -Like @code{malloc}, @code{realloc} and @code{reallocarray} may return a null -pointer if no memory space is available to make the block bigger. When this -happens, the original block is untouched; it has not been modified or -relocated. - -In most cases it makes no difference what happens to the original block -when @code{realloc} fails, because the application program cannot continue -when it is out of memory, and the only thing to do is to give a fatal error -message. Often it is convenient to write and use a subroutine, -conventionally called @code{xrealloc}, that takes care of the error message -as @code{xmalloc} does for @code{malloc}: - -@smallexample -void * -xrealloc (void *ptr, size_t size) -@{ - void *value = realloc (ptr, size); - if (value == 0) - fatal ("Virtual memory exhausted"); - return value; -@} -@end smallexample - -You can also use @code{realloc} or @code{reallocarray} to make a block -smaller. The reason you would do this is to avoid tying up a lot of memory -space when only a little is needed. -@comment The following is no longer true with the new malloc. -@comment But it seems wise to keep the warning for other implementations. -In several allocation implementations, making a block smaller sometimes -necessitates copying it, so it can fail if no other space is available. - -If the new size you specify is the same as the old size, @code{realloc} and -@code{reallocarray} are guaranteed to change nothing and return the same -address that you gave. - -@node Allocating Cleared Space -@subsubsection Allocating Cleared Space - -The function @code{calloc} allocates memory and clears it to zero. It -is declared in @file{stdlib.h}. -@pindex stdlib.h - -@comment malloc.h stdlib.h -@comment ISO -@deftypefun {void *} calloc (size_t @var{count}, size_t @var{eltsize}) -@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{} @acsfd{} @acsmem{}}} -@c Same caveats as malloc. - -@c __libc_calloc @asulock @aculock @acsfd @acsmem -@c *__malloc_hook dup unguarded -@c memset dup ok -@c arena_get @asulock @aculock @acsfd @acsmem -@c arena_lock dup @asulock @aculock @acsfd @acsmem -@c top dup ok -@c chunksize dup ok -@c heap_for_ptr dup ok -@c _int_malloc dup @acsfd @acsmem -@c arena_get_retry dup @asulock @aculock @acsfd @acsmem -@c mutex_unlock dup @aculock -@c mem2chunk dup ok -@c chunk_is_mmapped dup ok -@c MALLOC_ZERO ok -@c memset dup ok -This function allocates a block long enough to contain a vector of -@var{count} elements, each of size @var{eltsize}. Its contents are -cleared to zero before @code{calloc} returns. -@end deftypefun - -You could define @code{calloc} as follows: - -@smallexample -void * -calloc (size_t count, size_t eltsize) -@{ - size_t size = count * eltsize; - void *value = malloc (size); - if (value != 0) - memset (value, 0, size); - return value; -@} -@end smallexample - -But in general, it is not guaranteed that @code{calloc} calls -@code{malloc} internally. Therefore, if an application provides its own -@code{malloc}/@code{realloc}/@code{free} outside the C library, it -should always define @code{calloc}, too. - -@node Aligned Memory Blocks -@subsubsection Allocating Aligned Memory Blocks - -@cindex page boundary -@cindex alignment (with @code{malloc}) -@pindex stdlib.h -The address of a block returned by @code{malloc} or @code{realloc} in -@gnusystems{} is always a multiple of eight (or sixteen on 64-bit -systems). If you need a block whose address is a multiple of a higher -power of two than that, use @code{aligned_alloc} or @code{posix_memalign}. -@code{aligned_alloc} and @code{posix_memalign} are declared in -@file{stdlib.h}. - -@comment stdlib.h -@deftypefun {void *} aligned_alloc (size_t @var{alignment}, size_t @var{size}) -@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{} @acsfd{} @acsmem{}}} -@c Alias to memalign. -The @code{aligned_alloc} function allocates a block of @var{size} bytes whose -address is a multiple of @var{alignment}. The @var{alignment} must be a -power of two and @var{size} must be a multiple of @var{alignment}. - -The @code{aligned_alloc} function returns a null pointer on error and sets -@code{errno} to one of the following values: - -@table @code -@item ENOMEM -There was insufficient memory available to satisfy the request. - -@item EINVAL -@var{alignment} is not a power of two. - -This function was introduced in @w{ISO C11} and hence may have better -portability to modern non-POSIX systems than @code{posix_memalign}. -@end table - -@end deftypefun - -@comment malloc.h -@comment BSD -@deftypefun {void *} memalign (size_t @var{boundary}, size_t @var{size}) -@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{} @acsfd{} @acsmem{}}} -@c Same issues as malloc. The padding bytes are safely freed in -@c _int_memalign, with the arena still locked. - -@c __libc_memalign @asulock @aculock @acsfd @acsmem -@c *__memalign_hook dup unguarded -@c __libc_malloc dup @asulock @aculock @acsfd @acsmem -@c arena_get dup @asulock @aculock @acsfd @acsmem -@c _int_memalign @acsfd @acsmem -@c _int_malloc dup @acsfd @acsmem -@c checked_request2size dup ok -@c mem2chunk dup ok -@c chunksize dup ok -@c chunk_is_mmapped dup ok -@c set_head dup ok -@c chunk2mem dup ok -@c set_inuse_bit_at_offset dup ok -@c set_head_size dup ok -@c _int_free (have_lock) dup @acsfd @acsmem -@c chunk_at_offset dup ok -@c check_inuse_chunk dup ok -@c arena_get_retry dup @asulock @aculock @acsfd @acsmem -@c mutex_unlock dup @aculock -The @code{memalign} function allocates a block of @var{size} bytes whose -address is a multiple of @var{boundary}. The @var{boundary} must be a -power of two! The function @code{memalign} works by allocating a -somewhat larger block, and then returning an address within the block -that is on the specified boundary. - -The @code{memalign} function returns a null pointer on error and sets -@code{errno} to one of the following values: - -@table @code -@item ENOMEM -There was insufficient memory available to satisfy the request. - -@item EINVAL -@var{boundary} is not a power of two. - -@end table - -The @code{memalign} function is obsolete and @code{aligned_alloc} or -@code{posix_memalign} should be used instead. -@end deftypefun - -@comment stdlib.h -@comment POSIX -@deftypefun int posix_memalign (void **@var{memptr}, size_t @var{alignment}, size_t @var{size}) -@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{} @acsfd{} @acsmem{}}} -@c Calls memalign unless the requirements are not met (powerof2 macro is -@c safe given an automatic variable as an argument) or there's a -@c memalign hook (accessed unguarded, but safely). -The @code{posix_memalign} function is similar to the @code{memalign} -function in that it returns a buffer of @var{size} bytes aligned to a -multiple of @var{alignment}. But it adds one requirement to the -parameter @var{alignment}: the value must be a power of two multiple of -@code{sizeof (void *)}. - -If the function succeeds in allocation memory a pointer to the allocated -memory is returned in @code{*@var{memptr}} and the return value is zero. -Otherwise the function returns an error value indicating the problem. -The possible error values returned are: - -@table @code -@item ENOMEM -There was insufficient memory available to satisfy the request. - -@item EINVAL -@var{alignment} is not a power of two multiple of @code{sizeof (void *)}. - -@end table - -This function was introduced in POSIX 1003.1d. Although this function is -superseded by @code{aligned_alloc}, it is more portable to older POSIX -systems that do not support @w{ISO C11}. -@end deftypefun - -@comment malloc.h stdlib.h -@comment BSD -@deftypefun {void *} valloc (size_t @var{size}) -@safety{@prelim{}@mtunsafe{@mtuinit{}}@asunsafe{@asuinit{} @asulock{}}@acunsafe{@acuinit{} @aculock{} @acsfd{} @acsmem{}}} -@c __libc_valloc @mtuinit @asuinit @asulock @aculock @acsfd @acsmem -@c ptmalloc_init (once) @mtsenv @asulock @aculock @acsfd @acsmem -@c _dl_addr @asucorrupt? @aculock -@c __rtld_lock_lock_recursive (dl_load_lock) @asucorrupt? @aculock -@c _dl_find_dso_for_object ok, iterates over dl_ns and its _ns_loaded objs -@c the ok above assumes no partial updates on dl_ns and _ns_loaded -@c that could confuse a _dl_addr call in a signal handler -@c _dl_addr_inside_object ok -@c determine_info ok -@c __rtld_lock_unlock_recursive (dl_load_lock) @aculock -@c *_environ @mtsenv -@c next_env_entry ok -@c strcspn dup ok -@c __libc_mallopt dup @mtasuconst:mallopt [setting mp_] -@c __malloc_check_init @mtasuconst:malloc_hooks [setting hooks] -@c *__malloc_initialize_hook unguarded, ok -@c *__memalign_hook dup ok, unguarded -@c arena_get dup @asulock @aculock @acsfd @acsmem -@c _int_valloc @acsfd @acsmem -@c malloc_consolidate dup ok -@c _int_memalign dup @acsfd @acsmem -@c arena_get_retry dup @asulock @aculock @acsfd @acsmem -@c _int_memalign dup @acsfd @acsmem -@c mutex_unlock dup @aculock -Using @code{valloc} is like using @code{memalign} and passing the page size -as the value of the first argument. It is implemented like this: - -@smallexample -void * -valloc (size_t size) -@{ - return memalign (getpagesize (), size); -@} -@end smallexample - -@ref{Query Memory Parameters} for more information about the memory -subsystem. - -The @code{valloc} function is obsolete and @code{aligned_alloc} or -@code{posix_memalign} should be used instead. -@end deftypefun - -@node Malloc Tunable Parameters -@subsubsection Malloc Tunable Parameters - -You can adjust some parameters for dynamic memory allocation with the -@code{mallopt} function. This function is the general SVID/XPG -interface, defined in @file{malloc.h}. -@pindex malloc.h - -@deftypefun int mallopt (int @var{param}, int @var{value}) -@safety{@prelim{}@mtunsafe{@mtuinit{} @mtasuconst{:mallopt}}@asunsafe{@asuinit{} @asulock{}}@acunsafe{@acuinit{} @aculock{}}} -@c __libc_mallopt @mtuinit @mtasuconst:mallopt @asuinit @asulock @aculock -@c ptmalloc_init (once) dup @mtsenv @asulock @aculock @acsfd @acsmem -@c mutex_lock (main_arena->mutex) @asulock @aculock -@c malloc_consolidate dup ok -@c set_max_fast ok -@c mutex_unlock dup @aculock - -When calling @code{mallopt}, the @var{param} argument specifies the -parameter to be set, and @var{value} the new value to be set. Possible -choices for @var{param}, as defined in @file{malloc.h}, are: - -@comment TODO: @item M_CHECK_ACTION -@vtable @code -@item M_MMAP_MAX -The maximum number of chunks to allocate with @code{mmap}. Setting this -to zero disables all use of @code{mmap}. - -The default value of this parameter is @code{65536}. - -This parameter can also be set for the process at startup by setting the -environment variable @env{MALLOC_MMAP_MAX_} to the desired value. - -@item M_MMAP_THRESHOLD -All chunks larger than this value are allocated outside the normal -heap, using the @code{mmap} system call. This way it is guaranteed -that the memory for these chunks can be returned to the system on -@code{free}. Note that requests smaller than this threshold might still -be allocated via @code{mmap}. - -If this parameter is not set, the default value is set as 128 KiB and the -threshold is adjusted dynamically to suit the allocation patterns of the -program. If the parameter is set, the dynamic adjustment is disabled and the -value is set statically to the input value. - -This parameter can also be set for the process at startup by setting the -environment variable @env{MALLOC_MMAP_THRESHOLD_} to the desired value. -@comment TODO: @item M_MXFAST - -@item M_PERTURB -If non-zero, memory blocks are filled with values depending on some -low order bits of this parameter when they are allocated (except when -allocated by @code{calloc}) and freed. This can be used to debug the -use of uninitialized or freed heap memory. Note that this option does not -guarantee that the freed block will have any specific values. It only -guarantees that the content the block had before it was freed will be -overwritten. - -The default value of this parameter is @code{0}. - -This parameter can also be set for the process at startup by setting the -environment variable @env{MALLOC_MMAP_PERTURB_} to the desired value. - -@item M_TOP_PAD -This parameter determines the amount of extra memory to obtain from the system -when an arena needs to be extended. It also specifies the number of bytes to -retain when shrinking an arena. This provides the necessary hysteresis in heap -size such that excessive amounts of system calls can be avoided. - -The default value of this parameter is @code{0}. - -This parameter can also be set for the process at startup by setting the -environment variable @env{MALLOC_TOP_PAD_} to the desired value. - -@item M_TRIM_THRESHOLD -This is the minimum size (in bytes) of the top-most, releasable chunk -that will trigger a system call in order to return memory to the system. - -If this parameter is not set, the default value is set as 128 KiB and the -threshold is adjusted dynamically to suit the allocation patterns of the -program. If the parameter is set, the dynamic adjustment is disabled and the -value is set statically to the provided input. - -This parameter can also be set for the process at startup by setting the -environment variable @env{MALLOC_TRIM_THRESHOLD_} to the desired value. - -@item M_ARENA_TEST -This parameter specifies the number of arenas that can be created before the -test on the limit to the number of arenas is conducted. The value is ignored if -@code{M_ARENA_MAX} is set. - -The default value of this parameter is 2 on 32-bit systems and 8 on 64-bit -systems. - -This parameter can also be set for the process at startup by setting the -environment variable @env{MALLOC_ARENA_TEST} to the desired value. - -@item M_ARENA_MAX -This parameter sets the number of arenas to use regardless of the number of -cores in the system. - -The default value of this tunable is @code{0}, meaning that the limit on the -number of arenas is determined by the number of CPU cores online. For 32-bit -systems the limit is twice the number of cores online and on 64-bit systems, it -is eight times the number of cores online. Note that the default value is not -derived from the default value of M_ARENA_TEST and is computed independently. - -This parameter can also be set for the process at startup by setting the -environment variable @env{MALLOC_ARENA_MAX} to the desired value. -@end vtable - -@end deftypefun - -@node Heap Consistency Checking -@subsubsection Heap Consistency Checking - -@cindex heap consistency checking -@cindex consistency checking, of heap - -You can ask @code{malloc} to check the consistency of dynamic memory by -using the @code{mcheck} function. This function is a GNU extension, -declared in @file{mcheck.h}. -@pindex mcheck.h - -@comment mcheck.h -@comment GNU -@deftypefun int mcheck (void (*@var{abortfn}) (enum mcheck_status @var{status})) -@safety{@prelim{}@mtunsafe{@mtasurace{:mcheck} @mtasuconst{:malloc_hooks}}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{}}} -@c The hooks must be set up before malloc is first used, which sort of -@c implies @mtuinit/@asuinit but since the function is a no-op if malloc -@c was already used, that doesn't pose any safety issues. The actual -@c problem is with the hooks, designed for single-threaded -@c fully-synchronous operation: they manage an unguarded linked list of -@c allocated blocks, and get temporarily overwritten before calling the -@c allocation functions recursively while holding the old hooks. There -@c are no guards for thread safety, and inconsistent hooks may be found -@c within signal handlers or left behind in case of cancellation. - -Calling @code{mcheck} tells @code{malloc} to perform occasional -consistency checks. These will catch things such as writing -past the end of a block that was allocated with @code{malloc}. - -The @var{abortfn} argument is the function to call when an inconsistency -is found. If you supply a null pointer, then @code{mcheck} uses a -default function which prints a message and calls @code{abort} -(@pxref{Aborting a Program}). The function you supply is called with -one argument, which says what sort of inconsistency was detected; its -type is described below. - -It is too late to begin allocation checking once you have allocated -anything with @code{malloc}. So @code{mcheck} does nothing in that -case. The function returns @code{-1} if you call it too late, and -@code{0} otherwise (when it is successful). - -The easiest way to arrange to call @code{mcheck} early enough is to use -the option @samp{-lmcheck} when you link your program; then you don't -need to modify your program source at all. Alternatively you might use -a debugger to insert a call to @code{mcheck} whenever the program is -started, for example these gdb commands will automatically call @code{mcheck} -whenever the program starts: - -@smallexample -(gdb) break main -Breakpoint 1, main (argc=2, argv=0xbffff964) at whatever.c:10 -(gdb) command 1 -Type commands for when breakpoint 1 is hit, one per line. -End with a line saying just "end". ->call mcheck(0) ->continue ->end -(gdb) @dots{} -@end smallexample - -This will however only work if no initialization function of any object -involved calls any of the @code{malloc} functions since @code{mcheck} -must be called before the first such function. - -@end deftypefun - -@deftypefun {enum mcheck_status} mprobe (void *@var{pointer}) -@safety{@prelim{}@mtunsafe{@mtasurace{:mcheck} @mtasuconst{:malloc_hooks}}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{}}} -@c The linked list of headers may be modified concurrently by other -@c threads, and it may find a partial update if called from a signal -@c handler. It's mostly read only, so cancelling it might be safe, but -@c it will modify global state that, if cancellation hits at just the -@c right spot, may be left behind inconsistent. This path is only taken -@c if checkhdr finds an inconsistency. If the inconsistency could only -@c occur because of earlier undefined behavior, that wouldn't be an -@c additional safety issue problem, but because of the other concurrency -@c issues in the mcheck hooks, the apparent inconsistency could be the -@c result of mcheck's own internal data race. So, AC-Unsafe it is. - -The @code{mprobe} function lets you explicitly check for inconsistencies -in a particular allocated block. You must have already called -@code{mcheck} at the beginning of the program, to do its occasional -checks; calling @code{mprobe} requests an additional consistency check -to be done at the time of the call. - -The argument @var{pointer} must be a pointer returned by @code{malloc} -or @code{realloc}. @code{mprobe} returns a value that says what -inconsistency, if any, was found. The values are described below. -@end deftypefun - -@deftp {Data Type} {enum mcheck_status} -This enumerated type describes what kind of inconsistency was detected -in an allocated block, if any. Here are the possible values: - -@table @code -@item MCHECK_DISABLED -@code{mcheck} was not called before the first allocation. -No consistency checking can be done. -@item MCHECK_OK -No inconsistency detected. -@item MCHECK_HEAD -The data immediately before the block was modified. -This commonly happens when an array index or pointer -is decremented too far. -@item MCHECK_TAIL -The data immediately after the block was modified. -This commonly happens when an array index or pointer -is incremented too far. -@item MCHECK_FREE -The block was already freed. -@end table -@end deftp - -Another possibility to check for and guard against bugs in the use of -@code{malloc}, @code{realloc} and @code{free} is to set the environment -variable @code{MALLOC_CHECK_}. When @code{MALLOC_CHECK_} is set, a -special (less efficient) implementation is used which is designed to be -tolerant against simple errors, such as double calls of @code{free} with -the same argument, or overruns of a single byte (off-by-one bugs). Not -all such errors can be protected against, however, and memory leaks can -result. If @code{MALLOC_CHECK_} is set to @code{0}, any detected heap -corruption is silently ignored; if set to @code{1}, a diagnostic is -printed on @code{stderr}; if set to @code{2}, @code{abort} is called -immediately. This can be useful because otherwise a crash may happen -much later, and the true cause for the problem is then very hard to -track down. - -There is one problem with @code{MALLOC_CHECK_}: in SUID or SGID binaries -it could possibly be exploited since diverging from the normal programs -behavior it now writes something to the standard error descriptor. -Therefore the use of @code{MALLOC_CHECK_} is disabled by default for -SUID and SGID binaries. It can be enabled again by the system -administrator by adding a file @file{/etc/suid-debug} (the content is -not important it could be empty). - -So, what's the difference between using @code{MALLOC_CHECK_} and linking -with @samp{-lmcheck}? @code{MALLOC_CHECK_} is orthogonal with respect to -@samp{-lmcheck}. @samp{-lmcheck} has been added for backward -compatibility. Both @code{MALLOC_CHECK_} and @samp{-lmcheck} should -uncover the same bugs - but using @code{MALLOC_CHECK_} you don't need to -recompile your application. - -@node Hooks for Malloc -@subsubsection Memory Allocation Hooks -@cindex allocation hooks, for @code{malloc} - -@Theglibc{} lets you modify the behavior of @code{malloc}, -@code{realloc}, and @code{free} by specifying appropriate hook -functions. You can use these hooks to help you debug programs that use -dynamic memory allocation, for example. - -The hook variables are declared in @file{malloc.h}. -@pindex malloc.h - -@comment malloc.h -@comment GNU -@defvar __malloc_hook -The value of this variable is a pointer to the function that -@code{malloc} uses whenever it is called. You should define this -function to look like @code{malloc}; that is, like: - -@smallexample -void *@var{function} (size_t @var{size}, const void *@var{caller}) -@end smallexample - -The value of @var{caller} is the return address found on the stack when -the @code{malloc} function was called. This value allows you to trace -the memory consumption of the program. -@end defvar - -@comment malloc.h -@comment GNU -@defvar __realloc_hook -The value of this variable is a pointer to function that @code{realloc} -uses whenever it is called. You should define this function to look -like @code{realloc}; that is, like: - -@smallexample -void *@var{function} (void *@var{ptr}, size_t @var{size}, const void *@var{caller}) -@end smallexample - -The value of @var{caller} is the return address found on the stack when -the @code{realloc} function was called. This value allows you to trace the -memory consumption of the program. -@end defvar - -@comment malloc.h -@comment GNU -@defvar __free_hook -The value of this variable is a pointer to function that @code{free} -uses whenever it is called. You should define this function to look -like @code{free}; that is, like: - -@smallexample -void @var{function} (void *@var{ptr}, const void *@var{caller}) -@end smallexample - -The value of @var{caller} is the return address found on the stack when -the @code{free} function was called. This value allows you to trace the -memory consumption of the program. -@end defvar - -@comment malloc.h -@comment GNU -@defvar __memalign_hook -The value of this variable is a pointer to function that @code{aligned_alloc}, -@code{memalign}, @code{posix_memalign} and @code{valloc} use whenever they -are called. You should define this function to look like @code{aligned_alloc}; -that is, like: - -@smallexample -void *@var{function} (size_t @var{alignment}, size_t @var{size}, const void *@var{caller}) -@end smallexample - -The value of @var{caller} is the return address found on the stack when -the @code{aligned_alloc}, @code{memalign}, @code{posix_memalign} or -@code{valloc} functions are called. This value allows you to trace the -memory consumption of the program. -@end defvar - -You must make sure that the function you install as a hook for one of -these functions does not call that function recursively without restoring -the old value of the hook first! Otherwise, your program will get stuck -in an infinite recursion. Before calling the function recursively, one -should make sure to restore all the hooks to their previous value. When -coming back from the recursive call, all the hooks should be resaved -since a hook might modify itself. - -An issue to look out for is the time at which the malloc hook functions -can be safely installed. If the hook functions call the malloc-related -functions recursively, it is necessary that malloc has already properly -initialized itself at the time when @code{__malloc_hook} etc. is -assigned to. On the other hand, if the hook functions provide a -complete malloc implementation of their own, it is vital that the hooks -are assigned to @emph{before} the very first @code{malloc} call has -completed, because otherwise a chunk obtained from the ordinary, -un-hooked malloc may later be handed to @code{__free_hook}, for example. - -Here is an example showing how to use @code{__malloc_hook} and -@code{__free_hook} properly. It installs a function that prints out -information every time @code{malloc} or @code{free} is called. We just -assume here that @code{realloc} and @code{memalign} are not used in our -program. - -@smallexample -/* Prototypes for __malloc_hook, __free_hook */ -#include <malloc.h> - -/* Prototypes for our hooks. */ -static void my_init_hook (void); -static void *my_malloc_hook (size_t, const void *); -static void my_free_hook (void*, const void *); - -static void -my_init (void) -@{ - old_malloc_hook = __malloc_hook; - old_free_hook = __free_hook; - __malloc_hook = my_malloc_hook; - __free_hook = my_free_hook; -@} - -static void * -my_malloc_hook (size_t size, const void *caller) -@{ - void *result; - /* Restore all old hooks */ - __malloc_hook = old_malloc_hook; - __free_hook = old_free_hook; - /* Call recursively */ - result = malloc (size); - /* Save underlying hooks */ - old_malloc_hook = __malloc_hook; - old_free_hook = __free_hook; - /* @r{@code{printf} might call @code{malloc}, so protect it too.} */ - printf ("malloc (%u) returns %p\n", (unsigned int) size, result); - /* Restore our own hooks */ - __malloc_hook = my_malloc_hook; - __free_hook = my_free_hook; - return result; -@} - -static void -my_free_hook (void *ptr, const void *caller) -@{ - /* Restore all old hooks */ - __malloc_hook = old_malloc_hook; - __free_hook = old_free_hook; - /* Call recursively */ - free (ptr); - /* Save underlying hooks */ - old_malloc_hook = __malloc_hook; - old_free_hook = __free_hook; - /* @r{@code{printf} might call @code{free}, so protect it too.} */ - printf ("freed pointer %p\n", ptr); - /* Restore our own hooks */ - __malloc_hook = my_malloc_hook; - __free_hook = my_free_hook; -@} - -main () -@{ - my_init (); - @dots{} -@} -@end smallexample - -The @code{mcheck} function (@pxref{Heap Consistency Checking}) works by -installing such hooks. - -@c __morecore, __after_morecore_hook are undocumented -@c It's not clear whether to document them. - -@node Statistics of Malloc -@subsubsection Statistics for Memory Allocation with @code{malloc} - -@cindex allocation statistics -You can get information about dynamic memory allocation by calling the -@code{mallinfo} function. This function and its associated data type -are declared in @file{malloc.h}; they are an extension of the standard -SVID/XPG version. -@pindex malloc.h - -@comment malloc.h -@comment GNU -@deftp {Data Type} {struct mallinfo} -This structure type is used to return information about the dynamic -memory allocator. It contains the following members: - -@table @code -@item int arena -This is the total size of memory allocated with @code{sbrk} by -@code{malloc}, in bytes. - -@item int ordblks -This is the number of chunks not in use. (The memory allocator -internally gets chunks of memory from the operating system, and then -carves them up to satisfy individual @code{malloc} requests; -@pxref{The GNU Allocator}.) - -@item int smblks -This field is unused. - -@item int hblks -This is the total number of chunks allocated with @code{mmap}. - -@item int hblkhd -This is the total size of memory allocated with @code{mmap}, in bytes. - -@item int usmblks -This field is unused and always 0. - -@item int fsmblks -This field is unused. - -@item int uordblks -This is the total size of memory occupied by chunks handed out by -@code{malloc}. - -@item int fordblks -This is the total size of memory occupied by free (not in use) chunks. - -@item int keepcost -This is the size of the top-most releasable chunk that normally -borders the end of the heap (i.e., the high end of the virtual address -space's data segment). - -@end table -@end deftp - -@comment malloc.h -@comment SVID -@deftypefun {struct mallinfo} mallinfo (void) -@safety{@prelim{}@mtunsafe{@mtuinit{} @mtasuconst{:mallopt}}@asunsafe{@asuinit{} @asulock{}}@acunsafe{@acuinit{} @aculock{}}} -@c Accessing mp_.n_mmaps and mp_.max_mmapped_mem, modified with atomics -@c but non-atomically elsewhere, may get us inconsistent results. We -@c mark the statistics as unsafe, rather than the fast-path functions -@c that collect the possibly inconsistent data. - -@c __libc_mallinfo @mtuinit @mtasuconst:mallopt @asuinit @asulock @aculock -@c ptmalloc_init (once) dup @mtsenv @asulock @aculock @acsfd @acsmem -@c mutex_lock dup @asulock @aculock -@c int_mallinfo @mtasuconst:mallopt [mp_ access on main_arena] -@c malloc_consolidate dup ok -@c check_malloc_state dup ok/disabled -@c chunksize dup ok -@c fastbin dupo ok -@c bin_at dup ok -@c last dup ok -@c mutex_unlock @aculock - -This function returns information about the current dynamic memory usage -in a structure of type @code{struct mallinfo}. -@end deftypefun - -@node Summary of Malloc -@subsubsection Summary of @code{malloc}-Related Functions - -Here is a summary of the functions that work with @code{malloc}: - -@table @code -@item void *malloc (size_t @var{size}) -Allocate a block of @var{size} bytes. @xref{Basic Allocation}. - -@item void free (void *@var{addr}) -Free a block previously allocated by @code{malloc}. @xref{Freeing after -Malloc}. - -@item void *realloc (void *@var{addr}, size_t @var{size}) -Make a block previously allocated by @code{malloc} larger or smaller, -possibly by copying it to a new location. @xref{Changing Block Size}. - -@item void *reallocarray (void *@var{ptr}, size_t @var{nmemb}, size_t @var{size}) -Change the size of a block previously allocated by @code{malloc} to -@code{@var{nmemb} * @var{size}} bytes as with @code{realloc}. @xref{Changing -Block Size}. - -@item void *calloc (size_t @var{count}, size_t @var{eltsize}) -Allocate a block of @var{count} * @var{eltsize} bytes using -@code{malloc}, and set its contents to zero. @xref{Allocating Cleared -Space}. - -@item void *valloc (size_t @var{size}) -Allocate a block of @var{size} bytes, starting on a page boundary. -@xref{Aligned Memory Blocks}. - -@item void *aligned_alloc (size_t @var{size}, size_t @var{alignment}) -Allocate a block of @var{size} bytes, starting on an address that is a -multiple of @var{alignment}. @xref{Aligned Memory Blocks}. - -@item int posix_memalign (void **@var{memptr}, size_t @var{alignment}, size_t @var{size}) -Allocate a block of @var{size} bytes, starting on an address that is a -multiple of @var{alignment}. @xref{Aligned Memory Blocks}. - -@item void *memalign (size_t @var{size}, size_t @var{boundary}) -Allocate a block of @var{size} bytes, starting on an address that is a -multiple of @var{boundary}. @xref{Aligned Memory Blocks}. - -@item int mallopt (int @var{param}, int @var{value}) -Adjust a tunable parameter. @xref{Malloc Tunable Parameters}. - -@item int mcheck (void (*@var{abortfn}) (void)) -Tell @code{malloc} to perform occasional consistency checks on -dynamically allocated memory, and to call @var{abortfn} when an -inconsistency is found. @xref{Heap Consistency Checking}. - -@item void *(*__malloc_hook) (size_t @var{size}, const void *@var{caller}) -A pointer to a function that @code{malloc} uses whenever it is called. - -@item void *(*__realloc_hook) (void *@var{ptr}, size_t @var{size}, const void *@var{caller}) -A pointer to a function that @code{realloc} uses whenever it is called. - -@item void (*__free_hook) (void *@var{ptr}, const void *@var{caller}) -A pointer to a function that @code{free} uses whenever it is called. - -@item void (*__memalign_hook) (size_t @var{size}, size_t @var{alignment}, const void *@var{caller}) -A pointer to a function that @code{aligned_alloc}, @code{memalign}, -@code{posix_memalign} and @code{valloc} use whenever they are called. - -@item struct mallinfo mallinfo (void) -Return information about the current dynamic memory usage. -@xref{Statistics of Malloc}. -@end table - -@node Allocation Debugging -@subsection Allocation Debugging -@cindex allocation debugging -@cindex malloc debugger - -A complicated task when programming with languages which do not use -garbage collected dynamic memory allocation is to find memory leaks. -Long running programs must ensure that dynamically allocated objects are -freed at the end of their lifetime. If this does not happen the system -runs out of memory, sooner or later. - -The @code{malloc} implementation in @theglibc{} provides some -simple means to detect such leaks and obtain some information to find -the location. To do this the application must be started in a special -mode which is enabled by an environment variable. There are no speed -penalties for the program if the debugging mode is not enabled. - -@menu -* Tracing malloc:: How to install the tracing functionality. -* Using the Memory Debugger:: Example programs excerpts. -* Tips for the Memory Debugger:: Some more or less clever ideas. -* Interpreting the traces:: What do all these lines mean? -@end menu - -@node Tracing malloc -@subsubsection How to install the tracing functionality - -@comment mcheck.h -@comment GNU -@deftypefun void mtrace (void) -@safety{@prelim{}@mtunsafe{@mtsenv{} @mtasurace{:mtrace} @mtasuconst{:malloc_hooks} @mtuinit{}}@asunsafe{@asuinit{} @ascuheap{} @asucorrupt{} @asulock{}}@acunsafe{@acuinit{} @acucorrupt{} @aculock{} @acsfd{} @acsmem{}}} -@c Like the mcheck hooks, these are not designed with thread safety in -@c mind, because the hook pointers are temporarily modified without -@c regard to other threads, signals or cancellation. - -@c mtrace @mtuinit @mtasurace:mtrace @mtsenv @asuinit @ascuheap @asucorrupt @acuinit @acucorrupt @aculock @acsfd @acsmem -@c __libc_secure_getenv dup @mtsenv -@c malloc dup @ascuheap @acsmem -@c fopen dup @ascuheap @asulock @aculock @acsmem @acsfd -@c fcntl dup ok -@c setvbuf dup @aculock -@c fprintf dup (on newly-created stream) @aculock -@c __cxa_atexit (once) dup @asulock @aculock @acsmem -@c free dup @ascuheap @acsmem -When the @code{mtrace} function is called it looks for an environment -variable named @code{MALLOC_TRACE}. This variable is supposed to -contain a valid file name. The user must have write access. If the -file already exists it is truncated. If the environment variable is not -set or it does not name a valid file which can be opened for writing -nothing is done. The behavior of @code{malloc} etc. is not changed. -For obvious reasons this also happens if the application is installed -with the SUID or SGID bit set. - -If the named file is successfully opened, @code{mtrace} installs special -handlers for the functions @code{malloc}, @code{realloc}, and -@code{free} (@pxref{Hooks for Malloc}). From then on, all uses of these -functions are traced and protocolled into the file. There is now of -course a speed penalty for all calls to the traced functions so tracing -should not be enabled during normal use. - -This function is a GNU extension and generally not available on other -systems. The prototype can be found in @file{mcheck.h}. -@end deftypefun - -@comment mcheck.h -@comment GNU -@deftypefun void muntrace (void) -@safety{@prelim{}@mtunsafe{@mtasurace{:mtrace} @mtasuconst{:malloc_hooks} @mtslocale{}}@asunsafe{@asucorrupt{} @ascuheap{}}@acunsafe{@acucorrupt{} @acsmem{} @aculock{} @acsfd{}}} - -@c muntrace @mtasurace:mtrace @mtslocale @asucorrupt @ascuheap @acucorrupt @acsmem @aculock @acsfd -@c fprintf (fputs) dup @mtslocale @asucorrupt @ascuheap @acsmem @aculock @acucorrupt -@c fclose dup @ascuheap @asulock @aculock @acsmem @acsfd -The @code{muntrace} function can be called after @code{mtrace} was used -to enable tracing the @code{malloc} calls. If no (successful) call of -@code{mtrace} was made @code{muntrace} does nothing. - -Otherwise it deinstalls the handlers for @code{malloc}, @code{realloc}, -and @code{free} and then closes the protocol file. No calls are -protocolled anymore and the program runs again at full speed. - -This function is a GNU extension and generally not available on other -systems. The prototype can be found in @file{mcheck.h}. -@end deftypefun - -@node Using the Memory Debugger -@subsubsection Example program excerpts - -Even though the tracing functionality does not influence the runtime -behavior of the program it is not a good idea to call @code{mtrace} in -all programs. Just imagine that you debug a program using @code{mtrace} -and all other programs used in the debugging session also trace their -@code{malloc} calls. The output file would be the same for all programs -and thus is unusable. Therefore one should call @code{mtrace} only if -compiled for debugging. A program could therefore start like this: - -@example -#include <mcheck.h> - -int -main (int argc, char *argv[]) -@{ -#ifdef DEBUGGING - mtrace (); -#endif - @dots{} -@} -@end example - -This is all that is needed if you want to trace the calls during the -whole runtime of the program. Alternatively you can stop the tracing at -any time with a call to @code{muntrace}. It is even possible to restart -the tracing again with a new call to @code{mtrace}. But this can cause -unreliable results since there may be calls of the functions which are -not called. Please note that not only the application uses the traced -functions, also libraries (including the C library itself) use these -functions. - -This last point is also why it is not a good idea to call @code{muntrace} -before the program terminates. The libraries are informed about the -termination of the program only after the program returns from -@code{main} or calls @code{exit} and so cannot free the memory they use -before this time. - -So the best thing one can do is to call @code{mtrace} as the very first -function in the program and never call @code{muntrace}. So the program -traces almost all uses of the @code{malloc} functions (except those -calls which are executed by constructors of the program or used -libraries). - -@node Tips for the Memory Debugger -@subsubsection Some more or less clever ideas - -You know the situation. The program is prepared for debugging and in -all debugging sessions it runs well. But once it is started without -debugging the error shows up. A typical example is a memory leak that -becomes visible only when we turn off the debugging. If you foresee -such situations you can still win. Simply use something equivalent to -the following little program: - -@example -#include <mcheck.h> -#include <signal.h> - -static void -enable (int sig) -@{ - mtrace (); - signal (SIGUSR1, enable); -@} - -static void -disable (int sig) -@{ - muntrace (); - signal (SIGUSR2, disable); -@} - -int -main (int argc, char *argv[]) -@{ - @dots{} - - signal (SIGUSR1, enable); - signal (SIGUSR2, disable); - - @dots{} -@} -@end example - -I.e., the user can start the memory debugger any time s/he wants if the -program was started with @code{MALLOC_TRACE} set in the environment. -The output will of course not show the allocations which happened before -the first signal but if there is a memory leak this will show up -nevertheless. - -@node Interpreting the traces -@subsubsection Interpreting the traces - -If you take a look at the output it will look similar to this: - -@example -= Start -@ [0x8048209] - 0x8064cc8 -@ [0x8048209] - 0x8064ce0 -@ [0x8048209] - 0x8064cf8 -@ [0x80481eb] + 0x8064c48 0x14 -@ [0x80481eb] + 0x8064c60 0x14 -@ [0x80481eb] + 0x8064c78 0x14 -@ [0x80481eb] + 0x8064c90 0x14 -= End -@end example - -What this all means is not really important since the trace file is not -meant to be read by a human. Therefore no attention is given to -readability. Instead there is a program which comes with @theglibc{} -which interprets the traces and outputs a summary in an -user-friendly way. The program is called @code{mtrace} (it is in fact a -Perl script) and it takes one or two arguments. In any case the name of -the file with the trace output must be specified. If an optional -argument precedes the name of the trace file this must be the name of -the program which generated the trace. - -@example -drepper$ mtrace tst-mtrace log -No memory leaks. -@end example - -In this case the program @code{tst-mtrace} was run and it produced a -trace file @file{log}. The message printed by @code{mtrace} shows there -are no problems with the code, all allocated memory was freed -afterwards. - -If we call @code{mtrace} on the example trace given above we would get a -different outout: - -@example -drepper$ mtrace errlog -- 0x08064cc8 Free 2 was never alloc'd 0x8048209 -- 0x08064ce0 Free 3 was never alloc'd 0x8048209 -- 0x08064cf8 Free 4 was never alloc'd 0x8048209 - -Memory not freed: ------------------ - Address Size Caller -0x08064c48 0x14 at 0x80481eb -0x08064c60 0x14 at 0x80481eb -0x08064c78 0x14 at 0x80481eb -0x08064c90 0x14 at 0x80481eb -@end example - -We have called @code{mtrace} with only one argument and so the script -has no chance to find out what is meant with the addresses given in the -trace. We can do better: - -@example -drepper$ mtrace tst errlog -- 0x08064cc8 Free 2 was never alloc'd /home/drepper/tst.c:39 -- 0x08064ce0 Free 3 was never alloc'd /home/drepper/tst.c:39 -- 0x08064cf8 Free 4 was never alloc'd /home/drepper/tst.c:39 - -Memory not freed: ------------------ - Address Size Caller -0x08064c48 0x14 at /home/drepper/tst.c:33 -0x08064c60 0x14 at /home/drepper/tst.c:33 -0x08064c78 0x14 at /home/drepper/tst.c:33 -0x08064c90 0x14 at /home/drepper/tst.c:33 -@end example - -Suddenly the output makes much more sense and the user can see -immediately where the function calls causing the trouble can be found. - -Interpreting this output is not complicated. There are at most two -different situations being detected. First, @code{free} was called for -pointers which were never returned by one of the allocation functions. -This is usually a very bad problem and what this looks like is shown in -the first three lines of the output. Situations like this are quite -rare and if they appear they show up very drastically: the program -normally crashes. - -The other situation which is much harder to detect are memory leaks. As -you can see in the output the @code{mtrace} function collects all this -information and so can say that the program calls an allocation function -from line 33 in the source file @file{/home/drepper/tst-mtrace.c} four -times without freeing this memory before the program terminates. -Whether this is a real problem remains to be investigated. - -@node Replacing malloc -@subsection Replacing @code{malloc} - -@cindex @code{malloc} replacement -@cindex @code{LD_PRELOAD} and @code{malloc} -@cindex alternative @code{malloc} implementations -@cindex customizing @code{malloc} -@cindex interposing @code{malloc} -@cindex preempting @code{malloc} -@cindex replacing @code{malloc} -@Theglibc{} supports replacing the built-in @code{malloc} implementation -with a different allocator with the same interface. For dynamically -linked programs, this happens through ELF symbol interposition, either -using shared object dependencies or @code{LD_PRELOAD}. For static -linking, the @code{malloc} replacement library must be linked in before -linking against @code{libc.a} (explicitly or implicitly). - -@strong{Note:} Failure to provide a complete set of replacement -functions (that is, all the functions used by the application, -@theglibc{}, and other linked-in libraries) can lead to static linking -failures, and, at run time, to heap corruption and application crashes. - -The minimum set of functions which has to be provided by a custom -@code{malloc} is given in the table below. - -@table @code -@item malloc -@item free -@item calloc -@item realloc -@end table - -These @code{malloc}-related functions are required for @theglibc{} to -work.@footnote{Versions of @theglibc{} before 2.25 required that a -custom @code{malloc} defines @code{__libc_memalign} (with the same -interface as the @code{memalign} function).} - -The @code{malloc} implementation in @theglibc{} provides additional -functionality not used by the library itself, but which is often used by -other system libraries and applications. A general-purpose replacement -@code{malloc} implementation should provide definitions of these -functions, too. Their names are listed in the following table. - -@table @code -@item aligned_alloc -@item malloc_usable_size -@item memalign -@item posix_memalign -@item pvalloc -@item valloc -@end table - -In addition, very old applications may use the obsolete @code{cfree} -function. - -Further @code{malloc}-related functions such as @code{mallopt} or -@code{mallinfo} will not have any effect or return incorrect statistics -when a replacement @code{malloc} is in use. However, failure to replace -these functions typically does not result in crashes or other incorrect -application behavior, but may result in static linking failures. - -@node Obstacks -@subsection Obstacks -@cindex obstacks - -An @dfn{obstack} is a pool of memory containing a stack of objects. You -can create any number of separate obstacks, and then allocate objects in -specified obstacks. Within each obstack, the last object allocated must -always be the first one freed, but distinct obstacks are independent of -each other. - -Aside from this one constraint of order of freeing, obstacks are totally -general: an obstack can contain any number of objects of any size. They -are implemented with macros, so allocation is usually very fast as long as -the objects are usually small. And the only space overhead per object is -the padding needed to start each object on a suitable boundary. - -@menu -* Creating Obstacks:: How to declare an obstack in your program. -* Preparing for Obstacks:: Preparations needed before you can - use obstacks. -* Allocation in an Obstack:: Allocating objects in an obstack. -* Freeing Obstack Objects:: Freeing objects in an obstack. -* Obstack Functions:: The obstack functions are both - functions and macros. -* Growing Objects:: Making an object bigger by stages. -* Extra Fast Growing:: Extra-high-efficiency (though more - complicated) growing objects. -* Status of an Obstack:: Inquiries about the status of an obstack. -* Obstacks Data Alignment:: Controlling alignment of objects in obstacks. -* Obstack Chunks:: How obstacks obtain and release chunks; - efficiency considerations. -* Summary of Obstacks:: -@end menu - -@node Creating Obstacks -@subsubsection Creating Obstacks - -The utilities for manipulating obstacks are declared in the header -file @file{obstack.h}. -@pindex obstack.h - -@comment obstack.h -@comment GNU -@deftp {Data Type} {struct obstack} -An obstack is represented by a data structure of type @code{struct -obstack}. This structure has a small fixed size; it records the status -of the obstack and how to find the space in which objects are allocated. -It does not contain any of the objects themselves. You should not try -to access the contents of the structure directly; use only the functions -described in this chapter. -@end deftp - -You can declare variables of type @code{struct obstack} and use them as -obstacks, or you can allocate obstacks dynamically like any other kind -of object. Dynamic allocation of obstacks allows your program to have a -variable number of different stacks. (You can even allocate an -obstack structure in another obstack, but this is rarely useful.) - -All the functions that work with obstacks require you to specify which -obstack to use. You do this with a pointer of type @code{struct obstack -*}. In the following, we often say ``an obstack'' when strictly -speaking the object at hand is such a pointer. - -The objects in the obstack are packed into large blocks called -@dfn{chunks}. The @code{struct obstack} structure points to a chain of -the chunks currently in use. - -The obstack library obtains a new chunk whenever you allocate an object -that won't fit in the previous chunk. Since the obstack library manages -chunks automatically, you don't need to pay much attention to them, but -you do need to supply a function which the obstack library should use to -get a chunk. Usually you supply a function which uses @code{malloc} -directly or indirectly. You must also supply a function to free a chunk. -These matters are described in the following section. - -@node Preparing for Obstacks -@subsubsection Preparing for Using Obstacks - -Each source file in which you plan to use the obstack functions -must include the header file @file{obstack.h}, like this: - -@smallexample -#include <obstack.h> -@end smallexample - -@findex obstack_chunk_alloc -@findex obstack_chunk_free -Also, if the source file uses the macro @code{obstack_init}, it must -declare or define two functions or macros that will be called by the -obstack library. One, @code{obstack_chunk_alloc}, is used to allocate -the chunks of memory into which objects are packed. The other, -@code{obstack_chunk_free}, is used to return chunks when the objects in -them are freed. These macros should appear before any use of obstacks -in the source file. - -Usually these are defined to use @code{malloc} via the intermediary -@code{xmalloc} (@pxref{Unconstrained Allocation}). This is done with -the following pair of macro definitions: - -@smallexample -#define obstack_chunk_alloc xmalloc -#define obstack_chunk_free free -@end smallexample - -@noindent -Though the memory you get using obstacks really comes from @code{malloc}, -using obstacks is faster because @code{malloc} is called less often, for -larger blocks of memory. @xref{Obstack Chunks}, for full details. - -At run time, before the program can use a @code{struct obstack} object -as an obstack, it must initialize the obstack by calling -@code{obstack_init}. - -@comment obstack.h -@comment GNU -@deftypefun int obstack_init (struct obstack *@var{obstack-ptr}) -@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acsafe{@acsmem{}}} -@c obstack_init @mtsrace:obstack-ptr @acsmem -@c _obstack_begin @acsmem -@c chunkfun = obstack_chunk_alloc (suggested malloc) -@c freefun = obstack_chunk_free (suggested free) -@c *chunkfun @acsmem -@c obstack_chunk_alloc user-supplied -@c *obstack_alloc_failed_handler user-supplied -@c -> print_and_abort (default) -@c -@c print_and_abort -@c _ dup @ascuintl -@c fxprintf dup @asucorrupt @aculock @acucorrupt -@c exit @acucorrupt? -Initialize obstack @var{obstack-ptr} for allocation of objects. This -function calls the obstack's @code{obstack_chunk_alloc} function. If -allocation of memory fails, the function pointed to by -@code{obstack_alloc_failed_handler} is called. The @code{obstack_init} -function always returns 1 (Compatibility notice: Former versions of -obstack returned 0 if allocation failed). -@end deftypefun - -Here are two examples of how to allocate the space for an obstack and -initialize it. First, an obstack that is a static variable: - -@smallexample -static struct obstack myobstack; -@dots{} -obstack_init (&myobstack); -@end smallexample - -@noindent -Second, an obstack that is itself dynamically allocated: - -@smallexample -struct obstack *myobstack_ptr - = (struct obstack *) xmalloc (sizeof (struct obstack)); - -obstack_init (myobstack_ptr); -@end smallexample - -@comment obstack.h -@comment GNU -@defvar obstack_alloc_failed_handler -The value of this variable is a pointer to a function that -@code{obstack} uses when @code{obstack_chunk_alloc} fails to allocate -memory. The default action is to print a message and abort. -You should supply a function that either calls @code{exit} -(@pxref{Program Termination}) or @code{longjmp} (@pxref{Non-Local -Exits}) and doesn't return. - -@smallexample -void my_obstack_alloc_failed (void) -@dots{} -obstack_alloc_failed_handler = &my_obstack_alloc_failed; -@end smallexample - -@end defvar - -@node Allocation in an Obstack -@subsubsection Allocation in an Obstack -@cindex allocation (obstacks) - -The most direct way to allocate an object in an obstack is with -@code{obstack_alloc}, which is invoked almost like @code{malloc}. - -@comment obstack.h -@comment GNU -@deftypefun {void *} obstack_alloc (struct obstack *@var{obstack-ptr}, int @var{size}) -@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acunsafe{@acucorrupt{} @acsmem{}}} -@c obstack_alloc @mtsrace:obstack-ptr @acucorrupt @acsmem -@c obstack_blank dup @mtsrace:obstack-ptr @acucorrupt @acsmem -@c obstack_finish dup @mtsrace:obstack-ptr @acucorrupt -This allocates an uninitialized block of @var{size} bytes in an obstack -and returns its address. Here @var{obstack-ptr} specifies which obstack -to allocate the block in; it is the address of the @code{struct obstack} -object which represents the obstack. Each obstack function or macro -requires you to specify an @var{obstack-ptr} as the first argument. - -This function calls the obstack's @code{obstack_chunk_alloc} function if -it needs to allocate a new chunk of memory; it calls -@code{obstack_alloc_failed_handler} if allocation of memory by -@code{obstack_chunk_alloc} failed. -@end deftypefun - -For example, here is a function that allocates a copy of a string @var{str} -in a specific obstack, which is in the variable @code{string_obstack}: - -@smallexample -struct obstack string_obstack; - -char * -copystring (char *string) -@{ - size_t len = strlen (string) + 1; - char *s = (char *) obstack_alloc (&string_obstack, len); - memcpy (s, string, len); - return s; -@} -@end smallexample - -To allocate a block with specified contents, use the function -@code{obstack_copy}, declared like this: - -@comment obstack.h -@comment GNU -@deftypefun {void *} obstack_copy (struct obstack *@var{obstack-ptr}, void *@var{address}, int @var{size}) -@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acunsafe{@acucorrupt{} @acsmem{}}} -@c obstack_copy @mtsrace:obstack-ptr @acucorrupt @acsmem -@c obstack_grow dup @mtsrace:obstack-ptr @acucorrupt @acsmem -@c obstack_finish dup @mtsrace:obstack-ptr @acucorrupt -This allocates a block and initializes it by copying @var{size} -bytes of data starting at @var{address}. It calls -@code{obstack_alloc_failed_handler} if allocation of memory by -@code{obstack_chunk_alloc} failed. -@end deftypefun - -@comment obstack.h -@comment GNU -@deftypefun {void *} obstack_copy0 (struct obstack *@var{obstack-ptr}, void *@var{address}, int @var{size}) -@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acunsafe{@acucorrupt{} @acsmem{}}} -@c obstack_copy0 @mtsrace:obstack-ptr @acucorrupt @acsmem -@c obstack_grow0 dup @mtsrace:obstack-ptr @acucorrupt @acsmem -@c obstack_finish dup @mtsrace:obstack-ptr @acucorrupt -Like @code{obstack_copy}, but appends an extra byte containing a null -character. This extra byte is not counted in the argument @var{size}. -@end deftypefun - -The @code{obstack_copy0} function is convenient for copying a sequence -of characters into an obstack as a null-terminated string. Here is an -example of its use: - -@smallexample -char * -obstack_savestring (char *addr, int size) -@{ - return obstack_copy0 (&myobstack, addr, size); -@} -@end smallexample - -@noindent -Contrast this with the previous example of @code{savestring} using -@code{malloc} (@pxref{Basic Allocation}). - -@node Freeing Obstack Objects -@subsubsection Freeing Objects in an Obstack -@cindex freeing (obstacks) - -To free an object allocated in an obstack, use the function -@code{obstack_free}. Since the obstack is a stack of objects, freeing -one object automatically frees all other objects allocated more recently -in the same obstack. - -@comment obstack.h -@comment GNU -@deftypefun void obstack_free (struct obstack *@var{obstack-ptr}, void *@var{object}) -@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acunsafe{@acucorrupt{}}} -@c obstack_free @mtsrace:obstack-ptr @acucorrupt -@c (obstack_free) @mtsrace:obstack-ptr @acucorrupt -@c *freefun dup user-supplied -If @var{object} is a null pointer, everything allocated in the obstack -is freed. Otherwise, @var{object} must be the address of an object -allocated in the obstack. Then @var{object} is freed, along with -everything allocated in @var{obstack-ptr} since @var{object}. -@end deftypefun - -Note that if @var{object} is a null pointer, the result is an -uninitialized obstack. To free all memory in an obstack but leave it -valid for further allocation, call @code{obstack_free} with the address -of the first object allocated on the obstack: - -@smallexample -obstack_free (obstack_ptr, first_object_allocated_ptr); -@end smallexample - -Recall that the objects in an obstack are grouped into chunks. When all -the objects in a chunk become free, the obstack library automatically -frees the chunk (@pxref{Preparing for Obstacks}). Then other -obstacks, or non-obstack allocation, can reuse the space of the chunk. - -@node Obstack Functions -@subsubsection Obstack Functions and Macros -@cindex macros - -The interfaces for using obstacks may be defined either as functions or -as macros, depending on the compiler. The obstack facility works with -all C compilers, including both @w{ISO C} and traditional C, but there are -precautions you must take if you plan to use compilers other than GNU C. - -If you are using an old-fashioned @w{non-ISO C} compiler, all the obstack -``functions'' are actually defined only as macros. You can call these -macros like functions, but you cannot use them in any other way (for -example, you cannot take their address). - -Calling the macros requires a special precaution: namely, the first -operand (the obstack pointer) may not contain any side effects, because -it may be computed more than once. For example, if you write this: - -@smallexample -obstack_alloc (get_obstack (), 4); -@end smallexample - -@noindent -you will find that @code{get_obstack} may be called several times. -If you use @code{*obstack_list_ptr++} as the obstack pointer argument, -you will get very strange results since the incrementation may occur -several times. - -In @w{ISO C}, each function has both a macro definition and a function -definition. The function definition is used if you take the address of the -function without calling it. An ordinary call uses the macro definition by -default, but you can request the function definition instead by writing the -function name in parentheses, as shown here: - -@smallexample -char *x; -void *(*funcp) (); -/* @r{Use the macro}. */ -x = (char *) obstack_alloc (obptr, size); -/* @r{Call the function}. */ -x = (char *) (obstack_alloc) (obptr, size); -/* @r{Take the address of the function}. */ -funcp = obstack_alloc; -@end smallexample - -@noindent -This is the same situation that exists in @w{ISO C} for the standard library -functions. @xref{Macro Definitions}. - -@strong{Warning:} When you do use the macros, you must observe the -precaution of avoiding side effects in the first operand, even in @w{ISO C}. - -If you use the GNU C compiler, this precaution is not necessary, because -various language extensions in GNU C permit defining the macros so as to -compute each argument only once. - -@node Growing Objects -@subsubsection Growing Objects -@cindex growing objects (in obstacks) -@cindex changing the size of a block (obstacks) - -Because memory in obstack chunks is used sequentially, it is possible to -build up an object step by step, adding one or more bytes at a time to the -end of the object. With this technique, you do not need to know how much -data you will put in the object until you come to the end of it. We call -this the technique of @dfn{growing objects}. The special functions -for adding data to the growing object are described in this section. - -You don't need to do anything special when you start to grow an object. -Using one of the functions to add data to the object automatically -starts it. However, it is necessary to say explicitly when the object is -finished. This is done with the function @code{obstack_finish}. - -The actual address of the object thus built up is not known until the -object is finished. Until then, it always remains possible that you will -add so much data that the object must be copied into a new chunk. - -While the obstack is in use for a growing object, you cannot use it for -ordinary allocation of another object. If you try to do so, the space -already added to the growing object will become part of the other object. - -@comment obstack.h -@comment GNU -@deftypefun void obstack_blank (struct obstack *@var{obstack-ptr}, int @var{size}) -@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acunsafe{@acucorrupt{} @acsmem{}}} -@c obstack_blank @mtsrace:obstack-ptr @acucorrupt @acsmem -@c _obstack_newchunk @mtsrace:obstack-ptr @acucorrupt @acsmem -@c *chunkfun dup @acsmem -@c *obstack_alloc_failed_handler dup user-supplied -@c *freefun -@c obstack_blank_fast dup @mtsrace:obstack-ptr -The most basic function for adding to a growing object is -@code{obstack_blank}, which adds space without initializing it. -@end deftypefun - -@comment obstack.h -@comment GNU -@deftypefun void obstack_grow (struct obstack *@var{obstack-ptr}, void *@var{data}, int @var{size}) -@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acunsafe{@acucorrupt{} @acsmem{}}} -@c obstack_grow @mtsrace:obstack-ptr @acucorrupt @acsmem -@c _obstack_newchunk dup @mtsrace:obstack-ptr @acucorrupt @acsmem -@c memcpy ok -To add a block of initialized space, use @code{obstack_grow}, which is -the growing-object analogue of @code{obstack_copy}. It adds @var{size} -bytes of data to the growing object, copying the contents from -@var{data}. -@end deftypefun - -@comment obstack.h -@comment GNU -@deftypefun void obstack_grow0 (struct obstack *@var{obstack-ptr}, void *@var{data}, int @var{size}) -@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acunsafe{@acucorrupt{} @acsmem{}}} -@c obstack_grow0 @mtsrace:obstack-ptr @acucorrupt @acsmem -@c (no sequence point between storing NUL and incrementing next_free) -@c (multiple changes to next_free => @acucorrupt) -@c _obstack_newchunk dup @mtsrace:obstack-ptr @acucorrupt @acsmem -@c memcpy ok -This is the growing-object analogue of @code{obstack_copy0}. It adds -@var{size} bytes copied from @var{data}, followed by an additional null -character. -@end deftypefun - -@comment obstack.h -@comment GNU -@deftypefun void obstack_1grow (struct obstack *@var{obstack-ptr}, char @var{c}) -@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acunsafe{@acucorrupt{} @acsmem{}}} -@c obstack_1grow @mtsrace:obstack-ptr @acucorrupt @acsmem -@c _obstack_newchunk dup @mtsrace:obstack-ptr @acucorrupt @acsmem -@c obstack_1grow_fast dup @mtsrace:obstack-ptr @acucorrupt @acsmem -To add one character at a time, use the function @code{obstack_1grow}. -It adds a single byte containing @var{c} to the growing object. -@end deftypefun - -@comment obstack.h -@comment GNU -@deftypefun void obstack_ptr_grow (struct obstack *@var{obstack-ptr}, void *@var{data}) -@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acunsafe{@acucorrupt{} @acsmem{}}} -@c obstack_ptr_grow @mtsrace:obstack-ptr @acucorrupt @acsmem -@c _obstack_newchunk dup @mtsrace:obstack-ptr @acucorrupt @acsmem -@c obstack_ptr_grow_fast dup @mtsrace:obstack-ptr -Adding the value of a pointer one can use the function -@code{obstack_ptr_grow}. It adds @code{sizeof (void *)} bytes -containing the value of @var{data}. -@end deftypefun - -@comment obstack.h -@comment GNU -@deftypefun void obstack_int_grow (struct obstack *@var{obstack-ptr}, int @var{data}) -@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acunsafe{@acucorrupt{} @acsmem{}}} -@c obstack_int_grow @mtsrace:obstack-ptr @acucorrupt @acsmem -@c _obstack_newchunk dup @mtsrace:obstack-ptr @acucorrupt @acsmem -@c obstack_int_grow_fast dup @mtsrace:obstack-ptr -A single value of type @code{int} can be added by using the -@code{obstack_int_grow} function. It adds @code{sizeof (int)} bytes to -the growing object and initializes them with the value of @var{data}. -@end deftypefun - -@comment obstack.h -@comment GNU -@deftypefun {void *} obstack_finish (struct obstack *@var{obstack-ptr}) -@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acunsafe{@acucorrupt{}}} -@c obstack_finish @mtsrace:obstack-ptr @acucorrupt -When you are finished growing the object, use the function -@code{obstack_finish} to close it off and return its final address. - -Once you have finished the object, the obstack is available for ordinary -allocation or for growing another object. - -This function can return a null pointer under the same conditions as -@code{obstack_alloc} (@pxref{Allocation in an Obstack}). -@end deftypefun - -When you build an object by growing it, you will probably need to know -afterward how long it became. You need not keep track of this as you grow -the object, because you can find out the length from the obstack just -before finishing the object with the function @code{obstack_object_size}, -declared as follows: - -@comment obstack.h -@comment GNU -@deftypefun int obstack_object_size (struct obstack *@var{obstack-ptr}) -@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acsafe{}} -This function returns the current size of the growing object, in bytes. -Remember to call this function @emph{before} finishing the object. -After it is finished, @code{obstack_object_size} will return zero. -@end deftypefun - -If you have started growing an object and wish to cancel it, you should -finish it and then free it, like this: - -@smallexample -obstack_free (obstack_ptr, obstack_finish (obstack_ptr)); -@end smallexample - -@noindent -This has no effect if no object was growing. - -@cindex shrinking objects -You can use @code{obstack_blank} with a negative size argument to make -the current object smaller. Just don't try to shrink it beyond zero -length---there's no telling what will happen if you do that. - -@node Extra Fast Growing -@subsubsection Extra Fast Growing Objects -@cindex efficiency and obstacks - -The usual functions for growing objects incur overhead for checking -whether there is room for the new growth in the current chunk. If you -are frequently constructing objects in small steps of growth, this -overhead can be significant. - -You can reduce the overhead by using special ``fast growth'' -functions that grow the object without checking. In order to have a -robust program, you must do the checking yourself. If you do this checking -in the simplest way each time you are about to add data to the object, you -have not saved anything, because that is what the ordinary growth -functions do. But if you can arrange to check less often, or check -more efficiently, then you make the program faster. - -The function @code{obstack_room} returns the amount of room available -in the current chunk. It is declared as follows: - -@comment obstack.h -@comment GNU -@deftypefun int obstack_room (struct obstack *@var{obstack-ptr}) -@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acsafe{}} -This returns the number of bytes that can be added safely to the current -growing object (or to an object about to be started) in obstack -@var{obstack-ptr} using the fast growth functions. -@end deftypefun - -While you know there is room, you can use these fast growth functions -for adding data to a growing object: - -@comment obstack.h -@comment GNU -@deftypefun void obstack_1grow_fast (struct obstack *@var{obstack-ptr}, char @var{c}) -@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acunsafe{@acucorrupt{} @acsmem{}}} -@c obstack_1grow_fast @mtsrace:obstack-ptr @acucorrupt @acsmem -@c (no sequence point between copying c and incrementing next_free) -The function @code{obstack_1grow_fast} adds one byte containing the -character @var{c} to the growing object in obstack @var{obstack-ptr}. -@end deftypefun - -@comment obstack.h -@comment GNU -@deftypefun void obstack_ptr_grow_fast (struct obstack *@var{obstack-ptr}, void *@var{data}) -@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acsafe{}} -@c obstack_ptr_grow_fast @mtsrace:obstack-ptr -The function @code{obstack_ptr_grow_fast} adds @code{sizeof (void *)} -bytes containing the value of @var{data} to the growing object in -obstack @var{obstack-ptr}. -@end deftypefun - -@comment obstack.h -@comment GNU -@deftypefun void obstack_int_grow_fast (struct obstack *@var{obstack-ptr}, int @var{data}) -@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acsafe{}} -@c obstack_int_grow_fast @mtsrace:obstack-ptr -The function @code{obstack_int_grow_fast} adds @code{sizeof (int)} bytes -containing the value of @var{data} to the growing object in obstack -@var{obstack-ptr}. -@end deftypefun - -@comment obstack.h -@comment GNU -@deftypefun void obstack_blank_fast (struct obstack *@var{obstack-ptr}, int @var{size}) -@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acsafe{}} -@c obstack_blank_fast @mtsrace:obstack-ptr -The function @code{obstack_blank_fast} adds @var{size} bytes to the -growing object in obstack @var{obstack-ptr} without initializing them. -@end deftypefun - -When you check for space using @code{obstack_room} and there is not -enough room for what you want to add, the fast growth functions -are not safe. In this case, simply use the corresponding ordinary -growth function instead. Very soon this will copy the object to a -new chunk; then there will be lots of room available again. - -So, each time you use an ordinary growth function, check afterward for -sufficient space using @code{obstack_room}. Once the object is copied -to a new chunk, there will be plenty of space again, so the program will -start using the fast growth functions again. - -Here is an example: - -@smallexample -@group -void -add_string (struct obstack *obstack, const char *ptr, int len) -@{ - while (len > 0) - @{ - int room = obstack_room (obstack); - if (room == 0) - @{ - /* @r{Not enough room. Add one character slowly,} - @r{which may copy to a new chunk and make room.} */ - obstack_1grow (obstack, *ptr++); - len--; - @} - else - @{ - if (room > len) - room = len; - /* @r{Add fast as much as we have room for.} */ - len -= room; - while (room-- > 0) - obstack_1grow_fast (obstack, *ptr++); - @} - @} -@} -@end group -@end smallexample - -@node Status of an Obstack -@subsubsection Status of an Obstack -@cindex obstack status -@cindex status of obstack - -Here are functions that provide information on the current status of -allocation in an obstack. You can use them to learn about an object while -still growing it. - -@comment obstack.h -@comment GNU -@deftypefun {void *} obstack_base (struct obstack *@var{obstack-ptr}) -@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acsafe{}} -This function returns the tentative address of the beginning of the -currently growing object in @var{obstack-ptr}. If you finish the object -immediately, it will have that address. If you make it larger first, it -may outgrow the current chunk---then its address will change! - -If no object is growing, this value says where the next object you -allocate will start (once again assuming it fits in the current -chunk). -@end deftypefun - -@comment obstack.h -@comment GNU -@deftypefun {void *} obstack_next_free (struct obstack *@var{obstack-ptr}) -@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acsafe{}} -This function returns the address of the first free byte in the current -chunk of obstack @var{obstack-ptr}. This is the end of the currently -growing object. If no object is growing, @code{obstack_next_free} -returns the same value as @code{obstack_base}. -@end deftypefun - -@comment obstack.h -@comment GNU -@deftypefun int obstack_object_size (struct obstack *@var{obstack-ptr}) -@c dup -@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acsafe{}} -This function returns the size in bytes of the currently growing object. -This is equivalent to - -@smallexample -obstack_next_free (@var{obstack-ptr}) - obstack_base (@var{obstack-ptr}) -@end smallexample -@end deftypefun - -@node Obstacks Data Alignment -@subsubsection Alignment of Data in Obstacks -@cindex alignment (in obstacks) - -Each obstack has an @dfn{alignment boundary}; each object allocated in -the obstack automatically starts on an address that is a multiple of the -specified boundary. By default, this boundary is aligned so that -the object can hold any type of data. - -To access an obstack's alignment boundary, use the macro -@code{obstack_alignment_mask}, whose function prototype looks like -this: - -@comment obstack.h -@comment GNU -@deftypefn Macro int obstack_alignment_mask (struct obstack *@var{obstack-ptr}) -@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} -The value is a bit mask; a bit that is 1 indicates that the corresponding -bit in the address of an object should be 0. The mask value should be one -less than a power of 2; the effect is that all object addresses are -multiples of that power of 2. The default value of the mask is a value -that allows aligned objects to hold any type of data: for example, if -its value is 3, any type of data can be stored at locations whose -addresses are multiples of 4. A mask value of 0 means an object can start -on any multiple of 1 (that is, no alignment is required). - -The expansion of the macro @code{obstack_alignment_mask} is an lvalue, -so you can alter the mask by assignment. For example, this statement: - -@smallexample -obstack_alignment_mask (obstack_ptr) = 0; -@end smallexample - -@noindent -has the effect of turning off alignment processing in the specified obstack. -@end deftypefn - -Note that a change in alignment mask does not take effect until -@emph{after} the next time an object is allocated or finished in the -obstack. If you are not growing an object, you can make the new -alignment mask take effect immediately by calling @code{obstack_finish}. -This will finish a zero-length object and then do proper alignment for -the next object. - -@node Obstack Chunks -@subsubsection Obstack Chunks -@cindex efficiency of chunks -@cindex chunks - -Obstacks work by allocating space for themselves in large chunks, and -then parceling out space in the chunks to satisfy your requests. Chunks -are normally 4096 bytes long unless you specify a different chunk size. -The chunk size includes 8 bytes of overhead that are not actually used -for storing objects. Regardless of the specified size, longer chunks -will be allocated when necessary for long objects. - -The obstack library allocates chunks by calling the function -@code{obstack_chunk_alloc}, which you must define. When a chunk is no -longer needed because you have freed all the objects in it, the obstack -library frees the chunk by calling @code{obstack_chunk_free}, which you -must also define. - -These two must be defined (as macros) or declared (as functions) in each -source file that uses @code{obstack_init} (@pxref{Creating Obstacks}). -Most often they are defined as macros like this: - -@smallexample -#define obstack_chunk_alloc malloc -#define obstack_chunk_free free -@end smallexample - -Note that these are simple macros (no arguments). Macro definitions with -arguments will not work! It is necessary that @code{obstack_chunk_alloc} -or @code{obstack_chunk_free}, alone, expand into a function name if it is -not itself a function name. - -If you allocate chunks with @code{malloc}, the chunk size should be a -power of 2. The default chunk size, 4096, was chosen because it is long -enough to satisfy many typical requests on the obstack yet short enough -not to waste too much memory in the portion of the last chunk not yet used. - -@comment obstack.h -@comment GNU -@deftypefn Macro int obstack_chunk_size (struct obstack *@var{obstack-ptr}) -@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} -This returns the chunk size of the given obstack. -@end deftypefn - -Since this macro expands to an lvalue, you can specify a new chunk size by -assigning it a new value. Doing so does not affect the chunks already -allocated, but will change the size of chunks allocated for that particular -obstack in the future. It is unlikely to be useful to make the chunk size -smaller, but making it larger might improve efficiency if you are -allocating many objects whose size is comparable to the chunk size. Here -is how to do so cleanly: - -@smallexample -if (obstack_chunk_size (obstack_ptr) < @var{new-chunk-size}) - obstack_chunk_size (obstack_ptr) = @var{new-chunk-size}; -@end smallexample - -@node Summary of Obstacks -@subsubsection Summary of Obstack Functions - -Here is a summary of all the functions associated with obstacks. Each -takes the address of an obstack (@code{struct obstack *}) as its first -argument. - -@table @code -@item void obstack_init (struct obstack *@var{obstack-ptr}) -Initialize use of an obstack. @xref{Creating Obstacks}. - -@item void *obstack_alloc (struct obstack *@var{obstack-ptr}, int @var{size}) -Allocate an object of @var{size} uninitialized bytes. -@xref{Allocation in an Obstack}. - -@item void *obstack_copy (struct obstack *@var{obstack-ptr}, void *@var{address}, int @var{size}) -Allocate an object of @var{size} bytes, with contents copied from -@var{address}. @xref{Allocation in an Obstack}. - -@item void *obstack_copy0 (struct obstack *@var{obstack-ptr}, void *@var{address}, int @var{size}) -Allocate an object of @var{size}+1 bytes, with @var{size} of them copied -from @var{address}, followed by a null character at the end. -@xref{Allocation in an Obstack}. - -@item void obstack_free (struct obstack *@var{obstack-ptr}, void *@var{object}) -Free @var{object} (and everything allocated in the specified obstack -more recently than @var{object}). @xref{Freeing Obstack Objects}. - -@item void obstack_blank (struct obstack *@var{obstack-ptr}, int @var{size}) -Add @var{size} uninitialized bytes to a growing object. -@xref{Growing Objects}. - -@item void obstack_grow (struct obstack *@var{obstack-ptr}, void *@var{address}, int @var{size}) -Add @var{size} bytes, copied from @var{address}, to a growing object. -@xref{Growing Objects}. - -@item void obstack_grow0 (struct obstack *@var{obstack-ptr}, void *@var{address}, int @var{size}) -Add @var{size} bytes, copied from @var{address}, to a growing object, -and then add another byte containing a null character. @xref{Growing -Objects}. - -@item void obstack_1grow (struct obstack *@var{obstack-ptr}, char @var{data-char}) -Add one byte containing @var{data-char} to a growing object. -@xref{Growing Objects}. - -@item void *obstack_finish (struct obstack *@var{obstack-ptr}) -Finalize the object that is growing and return its permanent address. -@xref{Growing Objects}. - -@item int obstack_object_size (struct obstack *@var{obstack-ptr}) -Get the current size of the currently growing object. @xref{Growing -Objects}. - -@item void obstack_blank_fast (struct obstack *@var{obstack-ptr}, int @var{size}) -Add @var{size} uninitialized bytes to a growing object without checking -that there is enough room. @xref{Extra Fast Growing}. - -@item void obstack_1grow_fast (struct obstack *@var{obstack-ptr}, char @var{data-char}) -Add one byte containing @var{data-char} to a growing object without -checking that there is enough room. @xref{Extra Fast Growing}. - -@item int obstack_room (struct obstack *@var{obstack-ptr}) -Get the amount of room now available for growing the current object. -@xref{Extra Fast Growing}. - -@item int obstack_alignment_mask (struct obstack *@var{obstack-ptr}) -The mask used for aligning the beginning of an object. This is an -lvalue. @xref{Obstacks Data Alignment}. - -@item int obstack_chunk_size (struct obstack *@var{obstack-ptr}) -The size for allocating chunks. This is an lvalue. @xref{Obstack Chunks}. - -@item void *obstack_base (struct obstack *@var{obstack-ptr}) -Tentative starting address of the currently growing object. -@xref{Status of an Obstack}. - -@item void *obstack_next_free (struct obstack *@var{obstack-ptr}) -Address just after the end of the currently growing object. -@xref{Status of an Obstack}. -@end table - -@node Variable Size Automatic -@subsection Automatic Storage with Variable Size -@cindex automatic freeing -@cindex @code{alloca} function -@cindex automatic storage with variable size - -The function @code{alloca} supports a kind of half-dynamic allocation in -which blocks are allocated dynamically but freed automatically. - -Allocating a block with @code{alloca} is an explicit action; you can -allocate as many blocks as you wish, and compute the size at run time. But -all the blocks are freed when you exit the function that @code{alloca} was -called from, just as if they were automatic variables declared in that -function. There is no way to free the space explicitly. - -The prototype for @code{alloca} is in @file{stdlib.h}. This function is -a BSD extension. -@pindex stdlib.h - -@comment stdlib.h -@comment GNU, BSD -@deftypefun {void *} alloca (size_t @var{size}) -@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} -The return value of @code{alloca} is the address of a block of @var{size} -bytes of memory, allocated in the stack frame of the calling function. -@end deftypefun - -Do not use @code{alloca} inside the arguments of a function call---you -will get unpredictable results, because the stack space for the -@code{alloca} would appear on the stack in the middle of the space for -the function arguments. An example of what to avoid is @code{foo (x, -alloca (4), y)}. -@c This might get fixed in future versions of GCC, but that won't make -@c it safe with compilers generally. - -@menu -* Alloca Example:: Example of using @code{alloca}. -* Advantages of Alloca:: Reasons to use @code{alloca}. -* Disadvantages of Alloca:: Reasons to avoid @code{alloca}. -* GNU C Variable-Size Arrays:: Only in GNU C, here is an alternative - method of allocating dynamically and - freeing automatically. -@end menu - -@node Alloca Example -@subsubsection @code{alloca} Example - -As an example of the use of @code{alloca}, here is a function that opens -a file name made from concatenating two argument strings, and returns a -file descriptor or minus one signifying failure: - -@smallexample -int -open2 (char *str1, char *str2, int flags, int mode) -@{ - char *name = (char *) alloca (strlen (str1) + strlen (str2) + 1); - stpcpy (stpcpy (name, str1), str2); - return open (name, flags, mode); -@} -@end smallexample - -@noindent -Here is how you would get the same results with @code{malloc} and -@code{free}: - -@smallexample -int -open2 (char *str1, char *str2, int flags, int mode) -@{ - char *name = (char *) malloc (strlen (str1) + strlen (str2) + 1); - int desc; - if (name == 0) - fatal ("virtual memory exceeded"); - stpcpy (stpcpy (name, str1), str2); - desc = open (name, flags, mode); - free (name); - return desc; -@} -@end smallexample - -As you can see, it is simpler with @code{alloca}. But @code{alloca} has -other, more important advantages, and some disadvantages. - -@node Advantages of Alloca -@subsubsection Advantages of @code{alloca} - -Here are the reasons why @code{alloca} may be preferable to @code{malloc}: - -@itemize @bullet -@item -Using @code{alloca} wastes very little space and is very fast. (It is -open-coded by the GNU C compiler.) - -@item -Since @code{alloca} does not have separate pools for different sizes of -blocks, space used for any size block can be reused for any other size. -@code{alloca} does not cause memory fragmentation. - -@item -@cindex longjmp -Nonlocal exits done with @code{longjmp} (@pxref{Non-Local Exits}) -automatically free the space allocated with @code{alloca} when they exit -through the function that called @code{alloca}. This is the most -important reason to use @code{alloca}. - -To illustrate this, suppose you have a function -@code{open_or_report_error} which returns a descriptor, like -@code{open}, if it succeeds, but does not return to its caller if it -fails. If the file cannot be opened, it prints an error message and -jumps out to the command level of your program using @code{longjmp}. -Let's change @code{open2} (@pxref{Alloca Example}) to use this -subroutine:@refill - -@smallexample -int -open2 (char *str1, char *str2, int flags, int mode) -@{ - char *name = (char *) alloca (strlen (str1) + strlen (str2) + 1); - stpcpy (stpcpy (name, str1), str2); - return open_or_report_error (name, flags, mode); -@} -@end smallexample - -@noindent -Because of the way @code{alloca} works, the memory it allocates is -freed even when an error occurs, with no special effort required. - -By contrast, the previous definition of @code{open2} (which uses -@code{malloc} and @code{free}) would develop a memory leak if it were -changed in this way. Even if you are willing to make more changes to -fix it, there is no easy way to do so. -@end itemize - -@node Disadvantages of Alloca -@subsubsection Disadvantages of @code{alloca} - -@cindex @code{alloca} disadvantages -@cindex disadvantages of @code{alloca} -These are the disadvantages of @code{alloca} in comparison with -@code{malloc}: - -@itemize @bullet -@item -If you try to allocate more memory than the machine can provide, you -don't get a clean error message. Instead you get a fatal signal like -the one you would get from an infinite recursion; probably a -segmentation violation (@pxref{Program Error Signals}). - -@item -Some @nongnusystems{} fail to support @code{alloca}, so it is less -portable. However, a slower emulation of @code{alloca} written in C -is available for use on systems with this deficiency. -@end itemize - -@node GNU C Variable-Size Arrays -@subsubsection GNU C Variable-Size Arrays -@cindex variable-sized arrays - -In GNU C, you can replace most uses of @code{alloca} with an array of -variable size. Here is how @code{open2} would look then: - -@smallexample -int open2 (char *str1, char *str2, int flags, int mode) -@{ - char name[strlen (str1) + strlen (str2) + 1]; - stpcpy (stpcpy (name, str1), str2); - return open (name, flags, mode); -@} -@end smallexample - -But @code{alloca} is not always equivalent to a variable-sized array, for -several reasons: - -@itemize @bullet -@item -A variable size array's space is freed at the end of the scope of the -name of the array. The space allocated with @code{alloca} -remains until the end of the function. - -@item -It is possible to use @code{alloca} within a loop, allocating an -additional block on each iteration. This is impossible with -variable-sized arrays. -@end itemize - -@strong{NB:} If you mix use of @code{alloca} and variable-sized arrays -within one function, exiting a scope in which a variable-sized array was -declared frees all blocks allocated with @code{alloca} during the -execution of that scope. - - -@node Resizing the Data Segment -@section Resizing the Data Segment - -The symbols in this section are declared in @file{unistd.h}. - -You will not normally use the functions in this section, because the -functions described in @ref{Memory Allocation} are easier to use. Those -are interfaces to a @glibcadj{} memory allocator that uses the -functions below itself. The functions below are simple interfaces to -system calls. - -@comment unistd.h -@comment BSD -@deftypefun int brk (void *@var{addr}) -@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} - -@code{brk} sets the high end of the calling process' data segment to -@var{addr}. - -The address of the end of a segment is defined to be the address of the -last byte in the segment plus 1. - -The function has no effect if @var{addr} is lower than the low end of -the data segment. (This is considered success, by the way.) - -The function fails if it would cause the data segment to overlap another -segment or exceed the process' data storage limit (@pxref{Limits on -Resources}). - -The function is named for a common historical case where data storage -and the stack are in the same segment. Data storage allocation grows -upward from the bottom of the segment while the stack grows downward -toward it from the top of the segment and the curtain between them is -called the @dfn{break}. - -The return value is zero on success. On failure, the return value is -@code{-1} and @code{errno} is set accordingly. The following @code{errno} -values are specific to this function: - -@table @code -@item ENOMEM -The request would cause the data segment to overlap another segment or -exceed the process' data storage limit. -@end table - -@c The Brk system call in Linux (as opposed to the GNU C Library function) -@c is considerably different. It always returns the new end of the data -@c segment, whether it succeeds or fails. The GNU C library Brk determines -@c it's a failure if and only if the system call returns an address less -@c than the address requested. - -@end deftypefun - - -@comment unistd.h -@comment BSD -@deftypefun void *sbrk (ptrdiff_t @var{delta}) -@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} - -This function is the same as @code{brk} except that you specify the new -end of the data segment as an offset @var{delta} from the current end -and on success the return value is the address of the resulting end of -the data segment instead of zero. - -This means you can use @samp{sbrk(0)} to find out what the current end -of the data segment is. - -@end deftypefun - - - -@node Locking Pages -@section Locking Pages -@cindex locking pages -@cindex memory lock -@cindex paging - -You can tell the system to associate a particular virtual memory page -with a real page frame and keep it that way --- i.e., cause the page to -be paged in if it isn't already and mark it so it will never be paged -out and consequently will never cause a page fault. This is called -@dfn{locking} a page. - -The functions in this chapter lock and unlock the calling process' -pages. - -@menu -* Why Lock Pages:: Reasons to read this section. -* Locked Memory Details:: Everything you need to know locked - memory -* Page Lock Functions:: Here's how to do it. -@end menu - -@node Why Lock Pages -@subsection Why Lock Pages - -Because page faults cause paged out pages to be paged in transparently, -a process rarely needs to be concerned about locking pages. However, -there are two reasons people sometimes are: - -@itemize @bullet - -@item -Speed. A page fault is transparent only insofar as the process is not -sensitive to how long it takes to do a simple memory access. Time-critical -processes, especially realtime processes, may not be able to wait or -may not be able to tolerate variance in execution speed. -@cindex realtime processing -@cindex speed of execution - -A process that needs to lock pages for this reason probably also needs -priority among other processes for use of the CPU. @xref{Priority}. - -In some cases, the programmer knows better than the system's demand -paging allocator which pages should remain in real memory to optimize -system performance. In this case, locking pages can help. - -@item -Privacy. If you keep secrets in virtual memory and that virtual memory -gets paged out, that increases the chance that the secrets will get out. -If a password gets written out to disk swap space, for example, it might -still be there long after virtual and real memory have been wiped clean. - -@end itemize - -Be aware that when you lock a page, that's one fewer page frame that can -be used to back other virtual memory (by the same or other processes), -which can mean more page faults, which means the system runs more -slowly. In fact, if you lock enough memory, some programs may not be -able to run at all for lack of real memory. - -@node Locked Memory Details -@subsection Locked Memory Details - -A memory lock is associated with a virtual page, not a real frame. The -paging rule is: If a frame backs at least one locked page, don't page it -out. - -Memory locks do not stack. I.e., you can't lock a particular page twice -so that it has to be unlocked twice before it is truly unlocked. It is -either locked or it isn't. - -A memory lock persists until the process that owns the memory explicitly -unlocks it. (But process termination and exec cause the virtual memory -to cease to exist, which you might say means it isn't locked any more). - -Memory locks are not inherited by child processes. (But note that on a -modern Unix system, immediately after a fork, the parent's and the -child's virtual address space are backed by the same real page frames, -so the child enjoys the parent's locks). @xref{Creating a Process}. - -Because of its ability to impact other processes, only the superuser can -lock a page. Any process can unlock its own page. - -The system sets limits on the amount of memory a process can have locked -and the amount of real memory it can have dedicated to it. @xref{Limits -on Resources}. - -In Linux, locked pages aren't as locked as you might think. -Two virtual pages that are not shared memory can nonetheless be backed -by the same real frame. The kernel does this in the name of efficiency -when it knows both virtual pages contain identical data, and does it -even if one or both of the virtual pages are locked. - -But when a process modifies one of those pages, the kernel must get it a -separate frame and fill it with the page's data. This is known as a -@dfn{copy-on-write page fault}. It takes a small amount of time and in -a pathological case, getting that frame may require I/O. -@cindex copy-on-write page fault -@cindex page fault, copy-on-write - -To make sure this doesn't happen to your program, don't just lock the -pages. Write to them as well, unless you know you won't write to them -ever. And to make sure you have pre-allocated frames for your stack, -enter a scope that declares a C automatic variable larger than the -maximum stack size you will need, set it to something, then return from -its scope. - -@node Page Lock Functions -@subsection Functions To Lock And Unlock Pages - -The symbols in this section are declared in @file{sys/mman.h}. These -functions are defined by POSIX.1b, but their availability depends on -your kernel. If your kernel doesn't allow these functions, they exist -but always fail. They @emph{are} available with a Linux kernel. - -@strong{Portability Note:} POSIX.1b requires that when the @code{mlock} -and @code{munlock} functions are available, the file @file{unistd.h} -define the macro @code{_POSIX_MEMLOCK_RANGE} and the file -@code{limits.h} define the macro @code{PAGESIZE} to be the size of a -memory page in bytes. It requires that when the @code{mlockall} and -@code{munlockall} functions are available, the @file{unistd.h} file -define the macro @code{_POSIX_MEMLOCK}. @Theglibc{} conforms to -this requirement. - -@comment sys/mman.h -@comment POSIX.1b -@deftypefun int mlock (const void *@var{addr}, size_t @var{len}) -@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} - -@code{mlock} locks a range of the calling process' virtual pages. - -The range of memory starts at address @var{addr} and is @var{len} bytes -long. Actually, since you must lock whole pages, it is the range of -pages that include any part of the specified range. - -When the function returns successfully, each of those pages is backed by -(connected to) a real frame (is resident) and is marked to stay that -way. This means the function may cause page-ins and have to wait for -them. - -When the function fails, it does not affect the lock status of any -pages. - -The return value is zero if the function succeeds. Otherwise, it is -@code{-1} and @code{errno} is set accordingly. @code{errno} values -specific to this function are: - -@table @code -@item ENOMEM -@itemize @bullet -@item -At least some of the specified address range does not exist in the -calling process' virtual address space. -@item -The locking would cause the process to exceed its locked page limit. -@end itemize - -@item EPERM -The calling process is not superuser. - -@item EINVAL -@var{len} is not positive. - -@item ENOSYS -The kernel does not provide @code{mlock} capability. - -@end table - -You can lock @emph{all} a process' memory with @code{mlockall}. You -unlock memory with @code{munlock} or @code{munlockall}. - -To avoid all page faults in a C program, you have to use -@code{mlockall}, because some of the memory a program uses is hidden -from the C code, e.g. the stack and automatic variables, and you -wouldn't know what address to tell @code{mlock}. - -@end deftypefun - -@comment sys/mman.h -@comment POSIX.1b -@deftypefun int munlock (const void *@var{addr}, size_t @var{len}) -@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} - -@code{munlock} unlocks a range of the calling process' virtual pages. - -@code{munlock} is the inverse of @code{mlock} and functions completely -analogously to @code{mlock}, except that there is no @code{EPERM} -failure. - -@end deftypefun - -@comment sys/mman.h -@comment POSIX.1b -@deftypefun int mlockall (int @var{flags}) -@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} - -@code{mlockall} locks all the pages in a process' virtual memory address -space, and/or any that are added to it in the future. This includes the -pages of the code, data and stack segment, as well as shared libraries, -user space kernel data, shared memory, and memory mapped files. - -@var{flags} is a string of single bit flags represented by the following -macros. They tell @code{mlockall} which of its functions you want. All -other bits must be zero. - -@vtable @code - -@item MCL_CURRENT -Lock all pages which currently exist in the calling process' virtual -address space. - -@item MCL_FUTURE -Set a mode such that any pages added to the process' virtual address -space in the future will be locked from birth. This mode does not -affect future address spaces owned by the same process so exec, which -replaces a process' address space, wipes out @code{MCL_FUTURE}. -@xref{Executing a File}. - -@end vtable - -When the function returns successfully, and you specified -@code{MCL_CURRENT}, all of the process' pages are backed by (connected -to) real frames (they are resident) and are marked to stay that way. -This means the function may cause page-ins and have to wait for them. - -When the process is in @code{MCL_FUTURE} mode because it successfully -executed this function and specified @code{MCL_CURRENT}, any system call -by the process that requires space be added to its virtual address space -fails with @code{errno} = @code{ENOMEM} if locking the additional space -would cause the process to exceed its locked page limit. In the case -that the address space addition that can't be accommodated is stack -expansion, the stack expansion fails and the kernel sends a -@code{SIGSEGV} signal to the process. - -When the function fails, it does not affect the lock status of any pages -or the future locking mode. - -The return value is zero if the function succeeds. Otherwise, it is -@code{-1} and @code{errno} is set accordingly. @code{errno} values -specific to this function are: - -@table @code -@item ENOMEM -@itemize @bullet -@item -At least some of the specified address range does not exist in the -calling process' virtual address space. -@item -The locking would cause the process to exceed its locked page limit. -@end itemize - -@item EPERM -The calling process is not superuser. - -@item EINVAL -Undefined bits in @var{flags} are not zero. - -@item ENOSYS -The kernel does not provide @code{mlockall} capability. - -@end table - -You can lock just specific pages with @code{mlock}. You unlock pages -with @code{munlockall} and @code{munlock}. - -@end deftypefun - - -@comment sys/mman.h -@comment POSIX.1b -@deftypefun int munlockall (void) -@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} - -@code{munlockall} unlocks every page in the calling process' virtual -address space and turns off @code{MCL_FUTURE} future locking mode. - -The return value is zero if the function succeeds. Otherwise, it is -@code{-1} and @code{errno} is set accordingly. The only way this -function can fail is for generic reasons that all functions and system -calls can fail, so there are no specific @code{errno} values. - -@end deftypefun - - - - -@ignore -@c This was never actually implemented. -zw -@node Relocating Allocator -@section Relocating Allocator - -@cindex relocating memory allocator -Any system of dynamic memory allocation has overhead: the amount of -space it uses is more than the amount the program asks for. The -@dfn{relocating memory allocator} achieves very low overhead by moving -blocks in memory as necessary, on its own initiative. - -@c @menu -@c * Relocator Concepts:: How to understand relocating allocation. -@c * Using Relocator:: Functions for relocating allocation. -@c @end menu - -@node Relocator Concepts -@subsection Concepts of Relocating Allocation - -@ifinfo -The @dfn{relocating memory allocator} achieves very low overhead by -moving blocks in memory as necessary, on its own initiative. -@end ifinfo - -When you allocate a block with @code{malloc}, the address of the block -never changes unless you use @code{realloc} to change its size. Thus, -you can safely store the address in various places, temporarily or -permanently, as you like. This is not safe when you use the relocating -memory allocator, because any and all relocatable blocks can move -whenever you allocate memory in any fashion. Even calling @code{malloc} -or @code{realloc} can move the relocatable blocks. - -@cindex handle -For each relocatable block, you must make a @dfn{handle}---a pointer -object in memory, designated to store the address of that block. The -relocating allocator knows where each block's handle is, and updates the -address stored there whenever it moves the block, so that the handle -always points to the block. Each time you access the contents of the -block, you should fetch its address anew from the handle. - -To call any of the relocating allocator functions from a signal handler -is almost certainly incorrect, because the signal could happen at any -time and relocate all the blocks. The only way to make this safe is to -block the signal around any access to the contents of any relocatable -block---not a convenient mode of operation. @xref{Nonreentrancy}. - -@node Using Relocator -@subsection Allocating and Freeing Relocatable Blocks - -@pindex malloc.h -In the descriptions below, @var{handleptr} designates the address of the -handle. All the functions are declared in @file{malloc.h}; all are GNU -extensions. - -@comment malloc.h -@comment GNU -@c @deftypefun {void *} r_alloc (void **@var{handleptr}, size_t @var{size}) -This function allocates a relocatable block of size @var{size}. It -stores the block's address in @code{*@var{handleptr}} and returns -a non-null pointer to indicate success. - -If @code{r_alloc} can't get the space needed, it stores a null pointer -in @code{*@var{handleptr}}, and returns a null pointer. -@end deftypefun - -@comment malloc.h -@comment GNU -@c @deftypefun void r_alloc_free (void **@var{handleptr}) -This function is the way to free a relocatable block. It frees the -block that @code{*@var{handleptr}} points to, and stores a null pointer -in @code{*@var{handleptr}} to show it doesn't point to an allocated -block any more. -@end deftypefun - -@comment malloc.h -@comment GNU -@c @deftypefun {void *} r_re_alloc (void **@var{handleptr}, size_t @var{size}) -The function @code{r_re_alloc} adjusts the size of the block that -@code{*@var{handleptr}} points to, making it @var{size} bytes long. It -stores the address of the resized block in @code{*@var{handleptr}} and -returns a non-null pointer to indicate success. - -If enough memory is not available, this function returns a null pointer -and does not modify @code{*@var{handleptr}}. -@end deftypefun -@end ignore - - - - -@ignore -@comment No longer available... - -@comment @node Memory Warnings -@comment @section Memory Usage Warnings -@comment @cindex memory usage warnings -@comment @cindex warnings of memory almost full - -@pindex malloc.c -You can ask for warnings as the program approaches running out of memory -space, by calling @code{memory_warnings}. This tells @code{malloc} to -check memory usage every time it asks for more memory from the operating -system. This is a GNU extension declared in @file{malloc.h}. - -@comment malloc.h -@comment GNU -@comment @deftypefun void memory_warnings (void *@var{start}, void (*@var{warn-func}) (const char *)) -Call this function to request warnings for nearing exhaustion of virtual -memory. - -The argument @var{start} says where data space begins, in memory. The -allocator compares this against the last address used and against the -limit of data space, to determine the fraction of available memory in -use. If you supply zero for @var{start}, then a default value is used -which is right in most circumstances. - -For @var{warn-func}, supply a function that @code{malloc} can call to -warn you. It is called with a string (a warning message) as argument. -Normally it ought to display the string for the user to read. -@end deftypefun - -The warnings come when memory becomes 75% full, when it becomes 85% -full, and when it becomes 95% full. Above 95% you get another warning -each time memory usage increases. - -@end ignore |