Safe memory allocation
Overview
Safe memory allocation. More…
// global functions static bool te_alloc_adjust_extent(size_t total_length, size_t offset, size_t* extent); void* te_alloc_internal(size_t size, bool initialize, const char* filename, int line); void* te_realloc_internal(void* oldptr, size_t newsize, const char* filename, int line); static bool te_is_valid_alloc(size_t nmemb, size_t size); void* te_memdup_internal(const void* src, bool zero_terminated, size_t maxsize, const char* filename, int line); // macros #define TE_ALLOC(size_) #define TE_ALLOC_UNINITIALIZED(size_) #define TE_MEMDUP(src_, size_) #define TE_REALLOC(ptr_, newsize_) #define TE_STRDUP(src_) #define TE_STRNDUP(src_, maxsize_)
Detailed Documentation
Safe memory allocation.
Global Functions
static bool te_alloc_adjust_extent(size_t total_length, size_t offset, size_t* extent)
Ensure that offset + extent is not out of bounds.
The function adjusts the value in extent so that a chunk starting at extent lie completely within a buffer of total_length bytes.
The function handles unsigned overflows correctly, so e.g. extent may contain SIZE_MAX.
offset should be within total_length.
Parameters:
total_length |
Total length of a buffer. |
offset |
Offset of a chunk within the buffer. |
extent |
Length of the chunk. |
Returns:
true if extent was reduced.
void* te_alloc_internal(size_t size, bool initialize, const char* filename, int line)
Allocate size bytes and optionally fill allocated memory with zeroes.
This function should never be called directly, use TE_ALLOC() or TE_ALLOC_UNINITIALIZED() macros instead.
On requesting zero bytes, the function actually returns a 1-byte buffer capturing ISO C permitted behaviour of recent glibc.
Parameters:
size |
Number of bytes to allocate. |
initialize |
Zero the allocated memory if |
filename |
Caller’s filename. |
line |
Caller’s line. |
TE_FATAL_ERROR |
in an unlikely case of a memory allocation failure. |
Returns:
A pointer to a fresh memory block (never NULL).
void* te_realloc_internal(void* oldptr, size_t newsize, const char* filename, int line)
Reallocate oldptr to have the size of newsize.
If oldptr is NULL, it is an exact equivalent of te_alloc_internal().
This function should never be called directly, use TE_REALLOC() macro instead.
Unlike system realloc, this function aborts if a non-null oldptr is tried to resize to zero bytes the behaviour of system realloc is really ill-defined.
Parameters:
oldptr |
An existing memory block or |
newsize |
New size of the block. |
filename |
Caller’s filename. |
line |
Caller’s line. |
TE_FATAL_ERROR |
in an unlikely case of a memory allocation failure or zero-size reallocation. |
Returns:
A pointer to a reallocated block (never NULL, may be the same as oldptr).
static bool te_is_valid_alloc(size_t nmemb, size_t size)
Check whether an array of nmemb elements of size bytes can be allocated.
Basically, it checks that nmemb * size would fit into size_t; it does not check for available memory and so on.
The primary purpose of this function is to ensure that TE_ALLOC(x * y) would not erroneously return a small buffer due to overflow:
if (!te_is_valid_alloc(nmemb, size)) TEST_FAIL("Array is too large"); arr = TE_ALLOC(nmemb * size);
See Hacker’s Delight, 2nd Edition, section 2.12.4
Parameters:
nmemb |
Number of elements. |
size |
Size of an element. |
Returns:
true if an array of nmemb elements may be allocated.
void* te_memdup_internal(const void* src, bool zero_terminated, size_t maxsize, const char* filename, int line)
Copy a block of memory src.
This function should never be called directly,
c NULL if and only if src is NULL.
Parameters:
src |
Source buffer (may be |
zero_terminated |
If |
maxsize |
Maximum number of bytes to copy (may be less if |
filename |
Source filename. |
line |
|
TE_FATAL_ERROR |
in an unlikely case of a memory allocation failure. |
Returns:
A pointer to a fresh copy of src.
Macros
#define TE_ALLOC(size_)
Allocate size_ bytes and fill allocated memory with zeroes.
On requesting zero bytes, the macro actually returns a 1-byte buffer capturing ISO C permitted behaviour of recent glibc.
Parameters:
size_ |
Number of bytes to allocate. |
TE_FATAL_ERROR |
in an unlikely case of a memory allocation failure. |
Returns:
A pointer to a fresh memory block (never NULL).
#define TE_ALLOC_UNINITIALIZED(size_)
Allocate size_ bytes without initializing it.
In most cases TE_ALLOC() shall be used instead. This macro is intended for performance-critical cases where the caller would immediately initialize the memory block itself, e.g. with memset or memcpy.
On requesting zero bytes, the macro actually returns a 1-byte buffer capturing ISO C permitted behaviour of recent glibc.
Parameters:
size_ |
Number of bytes to allocate. |
TE_FATAL_ERROR |
in an unlikely case of a memory allocation failure. |
Returns:
A pointer to a fresh uninitialized memory block (never NULL).
#define TE_MEMDUP(src_, size_)
Make a copy of size_ bytes of memory starting from src_.
This macro is similar to memdup function found in OpenBSD and some other OSes.
c NULL if and only if src_ is NULL.
Refer to TE_ALLOC() on behaviour when size_ is zero.
Parameters:
src_ |
Source buffer (may be |
size_ |
|
TE_FATAL_ERROR |
in an unlikely case of a memory allocation failure. |
Returns:
A pointer to a fresh copy of src_.
#define TE_REALLOC(ptr_, newsize_)
Reallocate ptr_ to have the size of newsize_.
If ptr_ contains NULL, it is an exact equivalent of TE_ALLOC().
ptr_ must be an lvalue and its content is replaced upon reallocation, so the old invalidated address is not accessible anymore.
Unlike system realloc, this function aborts if a non-null ptr_ is tried to resize to zero bytes the behaviour of system realloc is really ill-defined.
Parameters:
ptr_ |
An lvalue holding an existing memory block or |
newsize_ |
New size of the block. |
TE_FATAL_ERROR |
in an unlikely case of a memory allocation failure or zero-size reallocation. |
#define TE_STRDUP(src_)
Make a copy of zero-terminated src_ like system strdup.
c NULL if and only if src_ is NULL.
Parameters:
src_ |
|
TE_FATAL_ERROR |
in an unlikely case of a memory allocation failure. |
Returns:
A pointer to a fresh copy of src_.
#define TE_STRNDUP(src_, maxsize_)
Make a copy of possibly zero-terminated src_ like system strndup.
The macro copies the content of src_ up to and including the first binary zero or the first maxsize_ bytes, whichever comes first.
The result is always zero-terminated.
c NULL if and only if src_ is NULL.
Parameters:
src_ |
A possibly zero-terminated string (may be |
maxsize_ |
|
TE_FATAL_ERROR |
in an unlikely case of a memory allocation failure. |
Returns:
A pointer to a fresh copy of src_.