• Mastering stack and heap for system reliability


    http://www.iar.com/Global/Resources/Developers_Toolbox/Building_and_debugging/Mastering_stack_and_heap_for_system_reliability.pdf

    1. Introduction

    The stack and the heap are fundamental to an embedded system. Setting up the stack and the heap
    properly is essential to system stability and reliability. Incorrectly used, they may cause your system to
    wreak havoc in the strangest ways. Stack and heap memory must be allocated statically by the
    programmer. Calculating the stack space is notoriously difficult for all but the smallest embedded
    systems, and underestimating stack usage can lead to serious runtime errors which can be difficult to
    find. On the other hand, overestimating stack usage means a waste of memory resources. Worst case
    maximum stack depth is very useful information in most embedded projects, as it greatly simplifies
    estimates of how much stack an application will need. Heap memory overflows gracefully but this is of
    no real comfort as few embedded applications are able to recover in such extreme out-of-memory
    conditions.

    2. A short introduction to stack and heap


    2.1 Scope

    The focus in this article is on reliable stack and heap design, and how to minimize stack and heap in a
    safe way.

    Desktop systems and embedded systems share some common stack and heap design errors and
    considerations, but differ completely in many other aspects. One example of a difference between these
    environments is the available memory. Windows and Linux default to 1 and 8 Mbytes of stack space; a
    number that can be increased even more. Heap space is only limited by the available physical memory
    and/or page file size. Embedded systems, on the other hand, have very limited memory resources
    especially when it comes to RAM space. There is clearly a need to minimize stack and heap in this
    restricted memory environment. Common to small embedded systems is that there is no virtual memory
    mechanism; allocation of stack, heap and global data (i.e. variables, TCP/IP, USB buffers, etc) is static
    and performed at the time when the application is built.

    We will address the special issues that arise in small embedded systems. We will not cover how to
    protect the stack and heap against attacks. This is a hot topic on desktop and mobile devices and is
    likely to be a threat to embedded systems as well in the future, if it isn’t already. 

    2.2 Stretching the limits

    Stretching the limits in everyday life can sometimes be rewarding but can also put you in trouble.
    Stretching the limits in programming when it comes to allocated data will definitely put you in trouble.
    Luckily, the trouble may hit you directly or during system testing, but it might also manifest itself when it
    is too late and the product has been delivered to thousands of customers or deployed in a remote
    environment.

    Overflowing allocated data can occur in all three storage areas; global, stack and heap memory. Writing
    to arrays or pointer references can cause accesses outside of the memory allocated to the object.
    Some array accesses can be validated by static analysis, for example by the compiler itself or a MISRA
    C checker:

    int array[32]; 
    array[35] = 0x1234; 

    When the array index is a variable expression, static analysis can no longer find all problems. Pointer
    references are also hard to trace by static analysis:

    int* p = malloc(32 * sizeof(int)); 
    p += 35; 
    *p = 0x1234; 

    Runtime methods to catch object overflow errors have been available for desktop systems for a long
    time, Purify, Insure++, and Valgrind, to name a few. These tools work by instrumenting the application
    code to validate memory references at runtime. This comes at the price of slowing down application
    execution speed dramatically and increasing code size, and has thus not become a usable method for
    small embedded systems.

    2.3 Stack

    The stack is the memory area where a program stores, for example:

    • local variables
    • return addresses
    • function arguments
    • compiler temporaries
    • interrupt contexts
    The life span of variables on the stack is limited to the duration of the
    function. As soon as the function returns, the used stack memory will be free
    for use by subsequent function calls.

    Stack memory has to be allocated statically by the programmer. The stack
    usually grows downwards in memory and if the memory area allocated for
    the stack isn’t large enough, the executing code writes to the area allocated
    below the stack and an overflow situation occurs. The area written to is
    usually the area where global and static variables are stored. So,
    underestimated stack usage can lead to serious runtime errors like
    overwritten variables, wild pointers, and corrupted return addresses. All of
    these errors can be very difficult to find. On the other hand, overestimating
    stack usage means a waste of memory resources.

    We will highlight some methods that can be used to reliably calculate the
    required stack size and detect stack related problems.

     

    2.4 Heap


    The heap is where the dynamic memory of the system is located. Dynamic memory and the heap can in
    many cases be considered optional in small embedded systems. Dynamic memory makes memory
    sharing possible between different pieces of a program. When one module does not need its allocated
    memory anymore, it simply returns it to the memory allocator to be reused by some other module.

    Some examples of data that is placed on the heap include:

    • Transient data objects
    • C++ new/delete
    • C++ STL containers
    • C++ exceptions
    Calculating heap space ranges from difficult to impossible in larger systems, because of the dynamic
    behavior of the application. Moreover there is not much tool support in the embedded world for
    measuring heap utilization, but we will discuss some methods.

    It is important to maintain heap integrity. Allocated data space is typically interspersed with critical
    memory allocator housekeeping data. Bad use of allocated data space will not only risk the corruption of
    other data space but may also corrupt the entire memory allocator and most likely crash the application.
    We will discuss some methods to aid checking for heap integrity.

    Another aspect to consider is that the real-time performance of the heap is not deterministic. Memory
    allocation time depends on such factors as previous use and the requested data space size. This is
    hardly on the wish list for the cycle-driven embedded developer.

    Even if the heap is a ccore topic in this article, the general guideline is to minimize heap usage in small embedded systems.

  • 相关阅读:
    Uva 11991 Easy Prblem from Rujia Liu ?
    BANK && IT
    随机数发生器(对拍)-----对比测试
    HDU 1695(GCD)
    欧拉定理与费马定理,离散对数定理
    POJ 2352 (stars)
    线段树
    codeforces 51C(Three Base Stations)
    codeforces 165B(Burning Midnight Oil)
    POJ 2785(4 Values whose Sum is 0)
  • 原文地址:https://www.cnblogs.com/shangdawei/p/3494488.html
Copyright © 2020-2023  润新知