The Hackerlab at regexps.com

Low-level Memory Management

up: libhackerlab
next: Arrays
prev: Machine-Specific Definitions

The programming interfaces described in this chapter provide some frequently needed functionality built on top of the standard functions malloc , realloc , and free .

There are functions that work like malloc and friends, but that cause the process to exit with an error message and a non-0 status if an allocation fails. See Allocate or Die.

There are functions that let you keep track of how much memory is used by a particular subsystem of your program, and limit that amount of memory if you choose. You can use these functions to trigger various forms of garbage collection. See Allocation With Limitations.

Finally, There are functions that operate on arrays of bytes. These do little more than replace standard functions such as memcpy , but are included for symmetry and completeness. See Array-of-Byte Functions.


Allocate or Die

up: Low-level Memory Management
next: Allocation With Limitations


#include <hackerlab/mem/must-malloc.h>

The functions in this section allocate memory. If an allocation fails, they call panic rather than returning. Thus, these functions may be used without checking for errors.

Function must_calloc

void * must_calloc (size_t amt);

Return a newly allocated block large enough to hold amt bytes. If no such block can be allocated, exit by calling panic . Fill the newly allocated memory with 0 bytes.



Function must_malloc

void * must_malloc (size_t amt);

Return a newly malloced block large enough to hold amt bytes. If no such block can be allocated, exit by calling panic .



Function must_realloc

void * must_realloc (void * ptr, size_t amt);

Return a malloced block large enough to hold amt bytes. If ptr is not 0 , it should point to a previously malloced block. The contents of the new block are initialized from the contents of ptr . If the new block is not the same as ptr , ptr is freed.

If no block can be allocated, exit by calling panic .



Function must_free

void must_free (void * ptr);

Free a block allocated by must_calloc , must_malloc , or must_realloc .




Allocation With Limitations

up: Low-level Memory Management
next: Array-of-Byte Functions
prev: Allocate or Die


#include <hackerlab/mem/alloc-limits.h>

In some situations it is desriable for a subsystem of a program to limit its use of memory, independently of the rest of the program. The alloc_limits functions are for such situations.

There are two steps to using the alloc_limits functions. First, you create an alloc_limits object which specifies how much memory your subsystem should, ideally, use, and how much it is permitted to use. See make_alloc_limits. Second, use functions like lim_malloc and lim_free instead of functions like malloc and free in the subsystem to which the limits apply.


Specifying Allocation Limits

up: Allocation With Limitations
next: Allocating and Freeing

An object of the opaque type alloc_limits records the rules which limit memory use in a particular subsystem.

Function make_alloc_limits

alloc_limits make_alloc_limits (t_uchar * name,
                                size_t threshold,
                                size_t failure_pt,
                                int panic_on_failure,
                                lim_free_memory_fn free_memory,
                                void * closure);

Create a new alloc_limits object.

name is the name of the subsystem to which these allocation limits apply. The name is useful for debugging purposes.

threshold specifies an ideal limit on the amount of memory used by your subsystem. If a subsystem attempts to allocate more than threshold bytes, the free_memory function for that subsystem is invoked (see below). threshold may be 0 , in which case the free_memory function is never invoked.

failure_pt specifies an absolute limit on the amount of memory used by your subsystem. Allocations beyond failure_pt fail (return 0 ).

panic_on_failure , if non-0, means that if the failure point is reached, or allocation fails, the program will exit with a message to the standard error stream and a non-0 status. If 0 , allocation failures return 0 .

free_memory is a function pointer:

     typedef void (*lim_free_memory_fn)(void * closure, 
                                        size_t needed);

It is called immediately before an allocation that would exceed threshold (if threshold is not 0 ). closure is as passed to make_alloc_limits (see below). needed is the number of bytes by which the proposed allocation causes the total amount of memory used by the subsystem to exceed threshold . It is completely safe to call lim_free from your free_memory function. It is possible to call lim_malloc or lim_realloc , but if your program does this, free_memory must be reentrant.

closure is an opaque value passed to free_memory .

If a new alloc_limits object can not be allocated, this function calls panic and does not return.

As an alternative to calling make_alloc_limits in some situations, three pre-defined allocation limits are declared in alloc-limits.h :

     extern alloc_limits lim_use_malloc;
     extern alloc_limits lim_use_must_malloc;
     extern alloc_limits lim_no_allocations;

Allocations performed with lim_use_malloc are unlimited and are effectively like allocations performed with malloc or realloc . Failed allocations return 0 .

Allocations performed with lim_use_must_malloc are unlimited and are effectively like allocations performed with must_malloc or must_realloc . Failed allocations cause the process to exit with a non-0 status.

Allocations performed with lim_no_allocations always fail and return 0 . lim_free has no effect when passed lim_no_allocations .



Function free_alloc_limits

void free_alloc_limits (alloc_limits limits);

Free an allocation limits object.



Function lim_set_threshold

size_t lim_set_threshold (alloc_limits it, size_t threshold);

Modify the threshold of an alloc_limits object. Return the old threshold .

This function does not immediately call free_memory , even if the total amount of memory allocated exceeds the new threshold .



Function lim_threshold

size_t lim_threshold (alloc_limits limits);

Return the current threshold of allocation limits limits .



Function lim_set_failure_pt

size_t lim_set_failure_pt (alloc_limits limits, size_t failure_pt);

Modify the failure_pt of an alloc_limits object. Return the old failure_pt .



Function lim_failure_pt

size_t lim_failure_pt (alloc_limits limits);

Return the failure_pt of allocation limits limits .



Function lim_is_panic_on_failure

int lim_is_panic_on_failure (alloc_limits limits);

Return the value of the panic_on_failure flag of allocation limits limits .



Function lim_set_panic_on_failure

int lim_set_panic_on_failure (alloc_limits limits, int value);

Set the panic_on_failure flag of allocation limits limits .

Return the old value.



Function lim_in_use

size_t lim_in_use (alloc_limits limits);

Return the amount (in bytes) of memory allocation charged to limits and not yet freed.



Function lim_high_water_mark

size_t lim_high_water_mark (alloc_limits limits);

Return the largest amount (in bytes) of outstanding memory allocation charged to limits during the lifetime of the process.




Allocating and Freeing

up: Allocation With Limitations
next: Reserving Limited Memory
prev: Specifying Allocation Limits

These functions allocate and free memory, similarly to malloc , realloc , and free , but with allocation limits.

Function lim_malloc

void * lim_malloc (alloc_limits limits, size_t amt);

Allocate amt bytes of memory.

If the allocation would exceed the threshold of limits , invoke the free_memory function first.

If the allocation would exceed the failure_pt of limits , or if the underlying malloc fails, return 0 (if the panic_on_failure flag of limits is 0 ) or exit the process with a non-0 status (if panic_on_failure is non-0).

Adjust the in_use and high_water_mark of limits .

If limits is 0 , this function works like must_malloc.



Function lim_zalloc

void * lim_zalloc (alloc_limits limits, size_t amt);

Use lim_malloc to attempt to allocate amt bytes of memory. If allocation succeeds, initialize that memory to all zero bytes.

Return the allocated region or 0 if allocation fails.



Function lim_soft_malloc

void * lim_soft_malloc (alloc_limits limits, size_t amt);

Allocate amt bytes of memory. Return the newly allocated memory.

If the allocation would exceed the failure_pt of limits , or if the underlying malloc fails, return 0 (if the panic_on_failure flag of limits is 0 ) or exit the process with a non-0 status.

Adjust the in_use and high_water_mark of limits .

This function does not invoke the free_memory function of limits , even if the allocation would exceed the threshold of limits .

If limits is 0 , this function works like must_malloc.



Function lim_realloc

void * lim_realloc (alloc_limits limits, void * prev, size_t amt);

Reallocate prev as amt bytes of memory. Copy (up to) amt bytes of data from prev to the newly allocated memory.

If the allocation would exceed the threshold of limits , invoke the free_memory function first.

If the allocation would exceed the failure_pt of limits , or if the underlying malloc fails, return 0 (if the panic_on_failure flag of limits is 0 ) or exit the process with a non-0 status.

Adjust the in_use and high_water_mark of limits .

If prev is 0 , this function behaves like lim_malloc .

If limits is 0 , this function works like must_realloc.



Function lim_soft_realloc

void * lim_soft_realloc (alloc_limits limits,
                         void * prev,
                         size_t amt);

Reallocate prev as amt bytes of memory. Copy (up to) amt bytes of data from prev to the newly allocated memory.

If the allocation would exceed the failure_pt of limits , or if the underlying malloc fails, return 0 (if the panic_on_failure flag of limits is 0 ) or exit the process with a non-0 status.

Adjust the in_use and high_water_mark of limits .

This function does not invoke the free_memory function of limits , even if the allocation would exceed the threshold of limits .

If limits is 0 , this function works like must_realloc.



Function lim_free

void lim_free (alloc_limits limits, void * ptr);

Free ptr . Adjust the in_use and high_water_mark values of limits .

If limits is 0 , this function works like must_free.




Reserving Limited Memory

up: Allocation With Limitations
prev: Allocating and Freeing

Function lim_prepare

int lim_prepare (alloc_limits limits, size_t amt);

Prepare for an allocation of amt bytes.

If such an allocation would exceed the threshold of limits , invoke the free_memory function first.

If the allocation would exceed the failure_pt of limits , return -1 . Otherwise, return 0 .

If limits is 0 , this function simply returns 0 .




Array-of-Byte Functions

up: Low-level Memory Management
prev: Allocation With Limitations


#include <hackerlab/mem/mem.h>

These functions operate on regions of memory as arrays of unsigned bytes with no further interpretation.

Function mem_set

void mem_set (t_uchar * mem, unsigned int c, size_t size);

Store size bytes of value c beginning at mem .



Function mem_set0

void mem_set0 (t_uchar * mem, size_t n);

Store n 0 bytes beginning at mem .



Function mem_move

void mem_move (t_uchar * to, const t_uchar * from, size_t amt);

Copy amt bytes from from to to . The source and destination regions may overlap.



Function mem_cmp

int mem_cmp (const t_uchar * m1, const t_uchar * m2, size_t amt);

Compare amt bytes starting at m1 and m2 . If a difference is found, immediately return -1 if the differing byte in m1 is less than the byte in m2 , 1 otherwise. If no difference is found, return 0 .



Function mem_occurrences

size_t mem_occurrences (const t_uchar * mem,
                        unsigned int c,
                        size_t size);

Search size bytes of data for occurences of byte c beginning at mem . Return the number of occurences found.



libhackerlab: The Hackerlab C Library
The Hackerlab at regexps.com