Memory Management

Static Allocations

  • C code globals
    • Compiler assigns memory addresses.
    • Go in the BSS section
      • Originally ‘Block Started by Symbol’
      • Makes more sense to think of it as ‘Better Save Space’
    • Uninitialized. Don’t expect it to be zeroed out. Could contain random values. Intitialize it before using.
    • Doesn’t actually take up any space in the object file is it’s just reserved space without data.
  • Assembly declarations
    • You need to pick the values and plan where things go.
  • Linker definition files
    • sourceware.org—ld <http://sourceware.org/binutils/docs/ld/>
    • Script files
      • Ram script
      • Flash script
      • Define the interrupt stacks
      • Set where the .text, .data, and .bss section go in memory.
      • The compiler can introduced the .eh_frame for use with exception handling. Disable with the -fno-exceptions flag.
    • Example is lpc2378_flash.ld
    • You can dump sections with the objdump tool.

Stacks

  • Allocated and released at runtime
  • Reserved at the beginning of a function when the stack pointer is moved forward.
  • Released when the function exits and the stack pointer moves back.
  • Allocation time is practically free.
  • Typically grows down in memory.
  • Compiler generates the stack management code for C/C++.

Heaps

  • Managed memory
  • Grow up in memory
  • Allocated and freed with explicitly function calls.
  • Support is implemented in the C-runtime or in the OS.
  • Allocation and releasing is much more expensive involves control structures, pointers, and control functions.
  • Fragmentation is an issue.
  • Heap functions are usually provided as part of an OS.

Memory Fragmentation

  • Its a problem with general purpose heaps.
  • Over time the heap’s memory becomes fragmented.
  • Little and odd sized sized allocations are scattered randomly throughout the heap.
  • Becomes harder and harder to find large contiguous block of memory.
  • Large allocation can start to fail.
    • That’s why you should check if the allocation worked even when there appears to be plenty of free memory.
  • Memory allocations can not be moved by the heap manager.
  • Allocations are given out as pointers. If the memory is moved then the pointers become invalid. Functions that try to use them will break.
  • OS has now way of knowing where the pointers are. Therefore there is no way it could change the pointers to point to the new locations.
  • That is why many OSs hand out handles instead of pointers.
    • Handles are references not pointers.
    • The references are usually indexes into tables of pointers.
    • Each use requires a look up.
    • It’s slower but then the OS can move the memory and change the pointers if it needs to since clients have references and not direct pointers to the memory.

Handling Memory Fragmention

  • Pre-allocating memory statically.

  • Using the heap only for large allocations.

  • Pooling memory

    • Allocate a large chunk at the beginning of the a section that will churn through a lot of memory.
    • Provide functions that manage allocations from the pool.
    • Section that churns memory only uses the pool for its memory.
    • At the end of the section, the entire pool is released.
    • Windows CE has functions that enable heap creation and heap destruction. Basically enabling heap pooling.
  • Kernels often rerange their own memory.

    • That’s whay they hand out handles instead of pointers.
    • Handles allow a level of indirection between the user and the resource.
    • The handle never changes, but the resouce can be moved.
    • Handles can be a simple index into a table of pointers.

Partition Manager

  • More expensive then a static or stack allocation.
  • Much cheaper and faster then a heap allocation.
  • Allocates the same size chunks.
  • Same size allocation reduces complexity.
  • Eliminates fragmentation problems.
  • Faster and more deterministic then malloc and free
  • Uses much less code.

uCOS Memory Partitioner

  • Simple partion based memory manager.
  • Takes pre-allocated chunks of memory.
  • Hands out same sized chunks.
  • Use Get to allocate a chunk and Put to free it or return it to the pool.
  • Does not do any bounds checking.
  • Each partion’s block size is fixed for the life of that partion.
  • Very effecient and constant speed.
  • Does not require the C-runtime support.
  • APIs
    • Create
    • Get
    • Put
    • Query