Cross-platform C SDK logo

Cross-platform C SDK

Memory

❮ Back
Next ❯
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 (...)
voidbmem_free (...)
voidbmem_set1 (...)
voidbmem_set4 (...)
voidbmem_set8 (...)
voidbmem_set16 (...)
voidbmem_set_u32 (...)
voidbmem_set_r32 (...)
intbmem_cmp (...)
bool_tbmem_is_zero (...)
voidbmem_set_zero (...)
voidbmem_zero (...)
voidbmem_zero_n (...)
voidbmem_copy (...)
voidbmem_copy_n (...)
voidbmem_move (...)
bool_tbmem_overlaps (...)
voidbmem_rev (...)
voidbmem_rev2 (...)
voidbmem_rev4 (...)
voidbmem_rev8 (...)
voidbmem_revcopy (...)
voidbmem_rev_elems (...)
voidbmem_swap (...)
voidbmem_swap_type (...)
voidbmem_shuffle (...)
voidbmem_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.

Scheme of the stack segment at various times of execution.
Figure 1: Stack state in different points of the program.
Listing 1: Two simple cases that cause the stack overflow.
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.

Diagram of heap segment fragmentation as program execution progresses.
Figure 2: Fragmentation of the heap during the execution of the process.
NAppGUI implements its own dynamic memory manager/auditor Heap 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.
❮ Back
Next ❯

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 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 mem.

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 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 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 mem.

new_size

New required size, in bytes.

align

Alignment. It must be power of 2.

Return

Pointer to the relocated block.

Remarks

Use Heap 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 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 dest.

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
byte_t mblock[10];
byte_t mask[4] = "abcd";
bmem_set4(mblock, 10, mask);
/* mblock = "abcdabcdab" */
dest

Pointer to the memory block.

size

Size in bytes of the block dest. It is not necessary to be a multiple of 4.

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 dest. It is not necessary to be a multiple of 8.

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 dest. It is not necessary to be a multiple of 16.

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 mem.

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 dest.


bmem_zero ()

Initialize an object with 0s.

void
bmem_zero(type *dest,
          type);
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
typedef struct
{
    uint32_t f1;
    real32_t f2;
    String *f3;
    ...
} MyType;

MyType t1;
bmem_zero(&t1, MyType);
/* t1 = {0} */
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.

❮ Back
Next ❯