[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
This chapter describes some useful tools associated with stack checking and analysis. In particular, it deals with dynamic and static stack usage measurements.
23.1 Stack Overflow Checking 23.2 Static Stack Usage Analysis 23.3 Dynamic Stack Usage Analysis
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
For most operating systems, gcc
does not perform stack overflow
checking by default. This means that if the main environment task or
some other task exceeds the available stack space, then unpredictable
behavior will occur. Most native systems offer some level of protection by
adding a guard page at the end of each task stack. This mechanism is usually
not enough for dealing properly with stack overflow situations because
a large local variable could "jump" above the guard page.
Furthermore, when the
guard page is hit, there may not be any space left on the stack for executing
the exception propagation code. Enabling stack checking avoids
such situations.
To activate stack checking, compile all units with the gcc option `-fstack-check'. For example:
gcc -c -fstack-check package1.adb |
Units compiled with this option will generate extra instructions to check
that any use of the stack (for procedure calls or for declaring local
variables in declare blocks) does not exceed the available stack space.
If the space is exceeded, then a Storage_Error
exception is raised.
For declared tasks, the stack size is controlled by the size
given in an applicable Storage_Size
pragma or by the value specified
at bind time with `-d' (see section 4.2 Switches for gnatbind
) or is set to
the default size as defined in the GNAT runtime otherwise.
For the environment task, the stack size depends on
system defaults and is unknown to the compiler. Stack checking
may still work correctly if a fixed
size stack is allocated, but this cannot be guaranteed.
To ensure that a clean exception is signalled for stack
overflow, set the environment variable
GNAT_STACK_LIMIT
to indicate the maximum
stack area that can be used, as in:
SET GNAT_STACK_LIMIT 1600 |
The limit is given in kilobytes, so the above declaration would set the stack limit of the environment task to 1.6 megabytes. Note that the only purpose of this usage is to limit the amount of stack used by the environment task. If it is necessary to increase the amount of stack for the environment task, then this is an operating systems issue, and must be addressed with the appropriate operating systems commands.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
A unit compiled with `-fstack-usage' will generate an extra file that specifies the maximum amount of stack used, on a per-function basis. The file has the same basename as the target object file with a `.su' extension. Each line of this file is made up of three fields:
static
, dynamic
, bounded
.
The second field corresponds to the size of the known part of the function frame.
The qualifier static
means that the function frame size
is purely static.
It usually means that all local variables have a static size.
In this case, the second field is a reliable measure of the function stack
utilization.
The qualifier dynamic
means that the function frame size is not static.
It happens mainly when some local variables have a dynamic size. When this
qualifier appears alone, the second field is not a reliable measure
of the function stack analysis. When it is qualified with bounded
, it
means that the second field is a reliable maximum of the function stack
utilization.
A unit compiled with `-Wstack-usage' will issue a warning for each subprogram whose stack usage might be larger than the specified amount of bytes. The wording is in keeping with the qualifier documented above.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
It is possible to measure the maximum amount of stack used by a task, by
adding a switch to gnatbind
, as:
$ gnatbind -u0 file |
With this option, at each task termination, its stack usage is output on `stderr'. It is not always convenient to output the stack usage when the program is still running. Hence, it is possible to delay this output until program termination. for a given number of tasks specified as the argument of the `-u' option. For instance:
$ gnatbind -u100 file |
will buffer the stack usage information of the first 100 tasks to terminate and output this info at program termination. Results are displayed in four columns:
Index | Task Name | Stack Size | Stack Usage
where:
The environment task stack, e.g., the stack that contains the main unit, is only processed when the environment variable GNAT_STACK_LIMIT is set.
The package GNAT.Task_Stack_Usage
provides facilities to get
stack usage reports at run-time. See its body for the details.
[ << ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |