Memory
This page has been automatically translated using the Google Translate API services. We are working on improving texts. Thank you for your understanding and patience.
Generic manipulation of memory blocks and heap handling.
Functions
byte_t* | bmem_malloc (...) |
byte_t* | bmem_realloc (...) |
byte_t* | bmem_aligned_malloc (...) |
byte_t* | bmem_aligned_realloc (...) |
void | bmem_free (...) |
void | bmem_set1 (...) |
void | bmem_set4 (...) |
void | bmem_set8 (...) |
void | bmem_set16 (...) |
void | bmem_set_u32 (...) |
void | bmem_set_r32 (...) |
int | bmem_cmp (...) |
bool_t | bmem_is_zero (...) |
void | bmem_set_zero (...) |
void | bmem_zero (...) |
void | bmem_zero_n (...) |
void | bmem_copy (...) |
void | bmem_copy_n (...) |
void | bmem_move (...) |
bool_t | bmem_overlaps (...) |
void | bmem_rev (...) |
void | bmem_rev2 (...) |
void | bmem_rev4 (...) |
void | bmem_rev8 (...) |
void | bmem_revcopy (...) |
void | bmem_rev_elems (...) |
void | bmem_swap (...) |
void | bmem_swap_type (...) |
void | bmem_shuffle (...) |
void | bmem_shuffle_n (...) |
From the programmer perspective, access to memory is done through variables and manipulated through the language operators (+, -, *, =, ...) and always in the same way, regardless of how the variables were created or in what memory zone they are hosted. Within bmem.h
we have several functions to make copies, assignments or checks of generic memory blocks. This module also defines functions for dynamic memory manipulation (Heap).
- Use bmem_malloc to reserve a dynamic memory block.
- Use bmem_free to free a block of dynamic memory.
- Use bmem_copy to copy the contents of two memory blocks, previously reserved.
1. Stack Segment
The memory of a compiled and running C program is divided into several segments. One of them is the stack, a space of variable but limited size, where local variables and function calls (call stack) are stored. It grows and shrinks as the process enters and leaves areas or functions (Figure 1). It is automatically managed by the compiler as a LIFO Last-in First-out structure, so it goes unnoticed most of the time, since it does not require extra attention from the programmer. We are aware of its existence when receiving the Stack Overflow error, usually caused by infinite recursion or the reservation of very large C vectors (Listing 1). The debugger allows us to inspect the state of the stack at execution time Debugging the program.
1 2 3 |
int func(int n) { func(n); } // Stack Overflow float v[2000000]; // Stack Overflow |
While the use of the stack is ideal due to its high performance, security and ease of use, sometimes falls short. On the one hand, it is necessary to foresee in the design time the amount of memory needed and define it statically (eg. struct Product pr[100];
), something very inflexible when it comes to building real applications. On the other hand, variables are destroyed when closing a scope or leaving a function, which prevents sharing data globally.
2. Heap Segment
The heap is a memory zone that the process can request on demand, through calls to the system. It is complementary to the stack and is characterized by:
- It can be accessed globally, from any point of the program through a pointer.
- The amount of available memory is practically unlimited.
- It is less efficient than the stack.
- Requires management. Operating systems provide functions for requesting dynamic memory blocks (
HeapAlloc()
,sbrk()
), being the responsibility of the process, or rather the programmer, to release these blocks when they are no longer needed.
As allocations and de-allocations can be made in any order, internal fragmentation occurs as the program progresses (Figure 2). Here would come into play the so-called memory manager, which are algorithms that allow optimizing the use of the heap by compacting it and reusing the released blocks. The standard C library provides the familiar functions malloc()/free()
, which implement a generic memory manager through system calls.
NAppGUI implements its own dynamic memory manager/auditor Heap - Memory manager very optimized to serve numerous requests of small size, which is what applications demand normally. bmem_malloc/bmem_free connect to the operating system through system calls and should not be used directly.
bmem_malloc ()
Reserve a memory block with the default alignment sizeof(void*)
.
byte_t* bmem_malloc(const uint32_t size);
size | Size in bytes of the block. |
Return
Pointer to the new block. Must be released with bmem_free when it is no longer necessary.
Remarks
Use Heap - Memory manager for more efficient and secure allocations.
bmem_realloc ()
Reallocs an existing memory block due to the expansion or reduction of it. Guarantees that the previous content of the block is preserved min(size, new_size)
. Try to do it without moving memory (in situ), but if it is not possible look for a new zone. It also guarantees the default alignment sizeof(void*)
if has to reserve a new block.
byte_t* bmem_realloc(byte_t *mem, const uint32_t size, const uint32_t new_size);
mem | Pointer to the original block to relocate. |
size | Size in bytes of the original block |
new_size | New required size, in bytes. |
Return
Pointer to the relocated block. It will be the same as the original pointer mem
if the relocation "in-situ" has been successful. Must be released with bmem_free when it is no longer necessary.
Remarks
Use Heap - Memory manager for more efficient and secure allocations.
bmem_aligned_malloc ()
Reserve a memory block with alignment.
byte_t* bmem_aligned_malloc(const uint32_t size, const uint32_t align);
size | Size in bytes of the block. |
align | Alignment. It must be power of 2. |
Return
Pointer to the new block. Must be released with bmem_free when it is no longer necessary.
Remarks
Use Heap - Memory manager for more efficient and secure allocations.
bmem_aligned_realloc ()
Like bmem_realloc, but it guarantees a specific alignment.
byte_t* bmem_aligned_realloc(byte_t *mem, const uint32_t size, const uint32_t new_size, const uint32_t align);
mem | Pointer to the original block to relocate. |
size | Size in bytes of the original block |
new_size | New required size, in bytes. |
align | Alignment. It must be power of 2. |
Return
Pointer to the relocated block.
Remarks
Use Heap - Memory manager for more efficient and secure allocations.
bmem_free ()
Free memory pointed by mem
, previously reserved by bmem_malloc, bmem_realloc or its equivalents with alignment.
void bmem_free(byte_t *mem);
mem | Pointer to the memory block to be released. |
Remarks
Use Heap - Memory manager for more efficient and secure allocations.
bmem_set1 ()
Fill a block of memory with the same 1-byte mask.
void bmem_set1(byte_t *dest, const uint32_t size, const byte_t mask);
dest | Pointer to the memory block. |
size | Size in bytes of the block |
mask | Mask. |
bmem_set4 ()
Fill a block of memory with the same 4-byte mask.
void bmem_set4(byte_t *dest, const uint32_t size, const byte_t *mask);
1 2 3 4 |
dest | Pointer to the memory block. |
size | Size in bytes of the block |
mask | 4-byte mask. |
bmem_set8 ()
Fill a block of memory with the same 8-byte mask.
void bmem_set8(byte_t *dest, const uint32_t size, const byte_t *mask);
dest | Pointer to the memory block. |
size | Size in bytes of the block |
mask | 8-byte mask. |
bmem_set16 ()
Fill a block of memory with the same 16-byte mask.
void bmem_set16(byte_t *dest, const uint32_t size, const byte_t *mask);
dest | Pointer to the memory block. |
size | Size in bytes of the block |
mask | 16-byte mask. |
bmem_set_u32 ()
Fill an array of type uint32_t with the same value.
void bmem_set_u32(uint32_t *dest, const uint32_t n, const uint32_t value);
dest | Pointer to the array. |
n | Array size (number of elements). |
value | Filling value. |
bmem_set_r32 ()
Fills an array of type real32_t with the same value.
void bmem_set_r32(real32_t *dest, const uint32_t n, const real32_t value);
dest | Pointer to the array. |
n | Array size (number of elements). |
value | Filling value. |
bmem_cmp ()
Compare two generic memory blocks.
int bmem_cmp(const byte_t *mem1, const byte_t *mem2, const uint32_t size);
mem1 | Pointer to the first block of memory. |
mem2 | Pointer to the second block of memory. |
size | Number of bytes to compare. |
Return
Comparison result.
bmem_is_zero ()
Check if a memory block is completely filled with 0s.
bool_t bmem_is_zero(const byte_t *mem, const uint32_t size);
mem | Pointer to the memory block. |
size | Size in bytes of the block |
Return
TRUE
if all positions are 0, otherwise FALSE
.
bmem_set_zero ()
Fill a memory block with 0s.
void bmem_set_zero(byte_t *dest, const uint32_t size);
dest | Pointer to the memory block that must be filled. |
size | Size in bytes of the block |
bmem_zero ()
Initialize an object with 0s.
void bmem_zero(type *dest, type);
1 2 3 4 5 6 7 8 9 10 11 |
dest | Pointer to the object. |
type | Object type. |
bmem_zero_n ()
Initialize an array of objects with 0s.
void bmem_zero_n(type *dest, const uint32_t n, type);
dest | Object array. |
n | Array size. |
type | Object type. |
bmem_copy ()
Copy the contents of one block in another. The blocks must not be overlapping.
void bmem_copy(byte_t *dest, const byte_t *src, const uint32_t size);
dest | Pointer to the destination block. |
src | Pointer to the source block. |
size | Number of bytes to copy. |
bmem_copy_n ()
Copy an array of objects to another location.
void bmem_copy_n(type *dest, const type *src, const uint32_t n, type);
1 2 3 |
real32_t v1[64]; real32_t v2[64]; = {1.f, 45.f, 12.4f, ...}; bmem_copy_n(v1, v2, 64, real32_t); |
dest | Pointer to the destination array. |
src | Pointer to the source array. |
n | Array size (number of elements, not bytes). |
type | Object type. |
bmem_move ()
Like bmem_copy, but the blocks can overlap.
void bmem_move(byte_t *dest, const byte_t *src, const uint32_t size);
dest | Pointer to the destination block. |
src | Pointer to the source block. |
size | Number of bytes to copy. |
Remarks
If we have the certainty that both blocks do not overlap, bmem_copy is much more efficient.
bmem_overlaps ()
Check if two memory blocks overlap.
bool_t bmem_overlaps(byte_t *mem1, byte_t *mem2, const uint32_t size1, const uint32_t size2);
mem1 | Pointer to the first block. |
mem2 | Pointer to the second block. |
size1 | Size of the first block (in bytes). |
size2 | Size of the second block (in bytes). |
Return
TRUE
if there is overlap.
bmem_rev ()
Reverts a memory block m[i] = m[ni-1]
.
void bmem_rev(byte_t *mem, const uint32_t size);
mem | Pointer to the memory block. |
size | Block size in bytes. |
bmem_rev2 ()
Reverts a 2-byte memory block.
void bmem_rev2(byte_t *mem);
mem | Pointer to the memory block. |
bmem_rev4 ()
Reverts a 4-byte memory block.
void bmem_rev4(byte_t *mem);
mem | Pointer to the memory block. |
bmem_rev8 ()
Reverts an 8-byte memory block.
void bmem_rev8(byte_t *mem);
mem | Pointer to the memory block. |
bmem_revcopy ()
Make a reverse copy of a memory block.
void bmem_revcopy(byte_t *dest, const byte_t *src, const uint32_t size);
dest | Pointer to the destination block. |
src | Pointer to the source block. |
size | Number of bytes to copy. |
bmem_rev_elems ()
Reverts the elements inside an array.
void bmem_rev_elems(type*, const uint32_t num_elems, type);
type* | Pointer to the beginning of the array. |
num_elems | Number of elements of the array. |
type | Object type. |
bmem_swap ()
Exchanges the contents of two memory blocks (not overlapping). At end, mem1[i] = mem2[i]
and mem2[i] = mem1[i]
.
void bmem_swap(byte_t *mem1, byte_t *mem2, const uint32_t size);
mem1 | Pointer to the first block. |
mem2 | Pointer to the second block. |
size | Number of bytes to be exchanged. |
bmem_swap_type ()
Exchange the contents of two objects.
void bmem_swap_type(type *obj1, type *obj2, type);
obj1 | First object. |
obj2 | Second object. |
type | Object type. |
bmem_shuffle ()
Randomly shuffles a memory block.
void bmem_shuffle(byte_t *mem, const uint32_t size, const uint32_t esize);
mem | Pointer to the memory block. |
size | Block size (number of elements). |
esize | Size of each element. |
Remarks
This function is based on a pseudo-random number generator. Use bmath_rand_seed to change the sequence.
bmem_shuffle_n ()
Randomly shuffle an object array.
void bmem_shuffle_n(type *array, const uint32_t size, type);
array | Elements array. |
size | Number of elements. |
type | Object type. |
Remarks
This function is based on a pseudo-random number generator. Use bmath_rand_seed to change the sequence.