In this section:
Overview
Insure++ adopts the following error reporting strategy by default:
- Error messages are coded with an uppercase string, such as READ_OVERFLOW or LEAK_SCOPE, and displayed. See Error Codes for a list of error condition messages.
- Only the first occurrence of a particular (unsuppressed) error at any given source line is shown.
- Error messages are sent to the console (stderr), the Insra GUI, or to a separate report file.
- Each error shows a stack trace of the previous routines, displayed all the way back to your main program.
Report File
Normally, error reports are displayed on the UNIX stderr I/O stream. See Viewing Results for information about sending output to Insra. If you wish to send both your program’s output and the Insure++ reports to a file, you can use the normal console redirection method.
An alternative is to redirect the output from Insure++ by adding the following option to your .psrc file:
insure++.report_file <filename.dat>
This tells Insure++ to write its reports to a .dat file, while allowing your program's output to display as it normally would. Whenever this option is in effect, you will see the following report banner in your console when your program starts to remind you that error messages are being redirected:
** Insure++ messages will be written to <filename> **
To suppress the display of this banner add the following option to your .psrc file:
insure++.report_banner off
The report file is normally overwritten each time your program executes, but you can force messages to be appended to an existing file with the following command:
insure++.report_overwrite false
If you want to keep track of the reports from multiple runs of your code, you can configure Insure++ to automatically generate file names based on a template. Define the template by embedding a string of characters with tokens, such as %d
, %p
, or %V
. Each of these is expanded to indicate a certain property of your program as indicated in the section Configuration Options (psrc).
The following example advanced report configuration option will generate a report named foo-errs.20181221103032
if executed with a program called foo
at 10:30 a.m. on December 21, 2018:
report_file %v-errs.%D
The last two digits in the file name are the seconds.
Programs that automatically fork will include a -%n
in their format strings unless a %n
or %p
token is explicitly added to the format string. This ensures that output from different processes will always end up in different report files.
You can also include environment variables in these filenames so that the following template generates the same filename as the previous example:
$HOME/reports/%v-errs.%D
This also ensures that the output is placed in the reports sub-directory of the user's HOME. This method is very useful for keeping track of program runs during development to see how things are progressing as time goes on.
Customizing the Output Format
By default, Insure++ displays a particular banner for each error report, which contains the filename and line number containing the error, and the error category found. For example:
[foo.c:10] **READ_UNINIT_MEM(copy)**
You can modify this format to meet your needs, such as enabling the editor in your integrated environment to search for the correct file and line number for each error.
You can customize the output by setting the error_format
option in your .psrc file. Use a string of characters to define the format. The string should contain embedded tokens that represent the various pieces of information that you might wish to view. See Filenames for additional information.
The error_format
option only takes effect if the Insure++ errors are being reported to the console or a file. If the errors are being sent to Insra, the error format in Insra will stay the same. For details on how to change where errors are sent, see Viewing Results.
Displaying Process Information
When using Insure++ with programs that fork into multiple processes, you might wish to display additional process-related information in your error reports.
You could add the following options, for example to generate errors that contains the name of the machine on which the process is running and its process ID:
error_format "%f, line %l: \n\tprocess %p@%h: %c"
The errors would take the following form:
foo.c, line 8: process 1184@gobi: READ_UNINIT_MEM(copy)
Displaying Error Timestamps
You can extend the error reports generated by Insure++ to include timestamps of errors occurrences. Add the %d
and/or %t
characters to the error report format as specified in the .psrc file.
For example, the following format includes a timestamp in the generated report:
insure++.error_format "%f:%l, %d %t <%c>"
The error will be in the following format:
foo.c:8, 12-Mar-2007 14:24:03 <READ_NULL>
Displaying Repeated Errors
By default, Insure++ only reports the first error of any given kind at a source line, but you can configure Insure++ to display additional occurrences of the same errors. Use the insure++.report_limit <number>
option to your .psrc file to specify how many times additional errors are displayed.
When set to 1
, Insure++ will only report the first error of each type on any line of code. Set to 0
to only include errors in summary reports and not at runtime. Disable to report all errors. See Report Summaries for more information.
All information is lost by showing only the first (or first few) errors at any source line. If you enable the report summary you will see the total number of each error at each source line.
Limiting the Number of Errors
If your program is generating too many errors for convenient analysis, you can arrange for it to exit (with a non-zero exit code) after displaying a certain number of errors by adding the following line to your .psrc file and re-running the program:
insure++.exit_on_error <number>
The program will exit after the indicated number of errors are displayed. If the number is less than or equal to 0
, all errors are displayed.
Changing Stack Traces
There are two potential modifications you can make to alter the appearance of the stack tracing information presented by Insure++ to indicate the location of an error. By default, Insure++ reads your program's symbol table at start-up time to get enough information to generate stack traces. To get file and line information, you will need to compile your programs with debugging information turned on (typically via the -g
switch). If this is a problem, Insure++ can generate its own stack traces for files compiled with Insure++.
You can select this mode by adding the following options to your .psrc file:
insure++.symbol_table off insure++.stack_internal on
The stack_internal
option will take effect after you recompile your program, while the symbol_table
option can be toggled at runtime. In this case, the stack trace will display the following message in place of the stack trace for routines which were not compiled with Insure++:
** routines not compiled with insure **
This will also make your program run faster, particularly at start-up, because the symbol table will not be read.
The value 0
is valid and effectively disables tracing.
The value -1
is the default and indicates that the full stack trace should be displayed, regardless of length.
Stack traces are also presented to show the function that calls the sequence when blocks of dynamically allocated memory were allocated and freed. In a manner similar to the stack_limit
option, the malloc_trace
and free_trace
options control how extensive these stack traces are.
Searching for Source Code
Normally, Insure++ remembers the directory in which each source file was compiled and looks there when trying to display lines of source code in error messages. Occasionally your source code will no longer exist in this directory, possibly because of some sophisticated “build” or “make” process.
You can add the source_path
option to your .prsc file in the current HOME directory to provide Insure++ with an alternative list of directories to search for source code:
source_path .:/users/me/src:/src
The list can contain any number of directories separated by colons.
Insure++’s error messages normally indicate the line of source code responsible for a problem on the second line of an error report, after the >>
mark. If this line is missing from the report, it means that the source code could not be found at runtime.
Suppressing Error Messages
You can completely suppress error messages for types of errors that you do not need to address. Suppressing errors prevents them from being displayed, although the errors will still be counted and displayed in the report summaries. Add the suppress
option to your .psrc file and re-run the program. For example:
insure++.suppress EXPR_NULL, PARM_DANGLING
You can also apply certain wildcards in this context so that, for instance, you can suppress all memory leak messages with the command:
insure++.suppress LEAK_*
You can also suppress all errors, which will only create an error summary:
insure++.suppress *
If the error code has sub-categories, you can disable them explicitly by listing the sub-category codes in parentheses after the name. For example:
insure++.suppress BAD_FORMAT(sign, compatible)
Alternatively, the following option would suppresses all sub-categories of the specified error class:
insure++.suppress BAD_FORMAT
Suppressing Error Messages by Context
You can also suppress and unsuppress error messages by context. For example, enter the following option to suppress READ_NULL
errors occurring in routines with names beginning with the characters sub:
insure++.suppress READ_NULL { sub* * }
The interpretation of this syntax is as follows:
- The stack context is enclosed by a pair of braces.
- Routine names can either appear in full or can contain the
*
or?
wildcard characters. The former matches any string, while the latter matches any single character. - An entry consisting of a single
*
character matches any number of functions, with any names. - Entries in the stack context are read from left to right with the leftmost entries appearing lowest (or most recently) in the call stack.
With these rules in mind, the previous entry is read as:
- The lowest function in the stack trace (that is, the function generating the error message) must have a name that begins with sub followed by any number of other characters.
- Any number of functions of any name may appear higher in the function call stack.
As an example, consider a case in which we are only interested in errors generated from the routine {{foobar}} or its descendants In this case, we can combine suppress and unsuppress options as follows:
Suppress: *
Unsuppress: * {* foobar * }
Error suppression is only possible for functions that appear in stack traces which list error locations. For example, consider the following error report for READ_DANGLING
:
block committed at: > f2() > f1() >stack trace where memory was decommitted: > f3() > e::g() >stack trace where the error occurred: > g2() > g1()
You may suppress either of the functions g1() or g2() where the error occurred by using one of the following options:
Suppress READ_DANGLING { * g1 * } Suppress READ_DANGLING { * g2 * } Suppress READ_DANGLING { g* * }
In this instance, however, you may not suppress either of the functions in the stack trace where memory was de-committed. Scope names require special handling. Substitute *
for ::
when suppressing functions that have a scope resolution. For example, to suppress READ_DANGLING
in Foo::bar ()
, specify the following:
suppress READ_DANGLING { * Foo*bar * }
As another drastic, but common, action is to suppress any errors generated from within calls to the X Window System libraries. If we assume that these functions have names which begin with either "X" or "_X", we could achieve this goal with the following statements:
insure++.suppress all { * X* * } insure++.suppress all { * _X* * }
This suppresses errors in any function (or its descendants) that begins with either of the two sequences.
Suppressing Messages by File and Line
You can suppress error messages based on the file and line generating the message. Use the following syntax for this type of suppression:
file:line# in file
The following example suppresses readbadindex
error messages at line 32 of foo.h
at both compile time and runtime:
suppress readbadindex at foo.h:32
The following example suppresses all parser warnings in header.h:
suppress parserwarning in header.h
Wildcards are not supported in filenames, but unlike stack trace suppressions, which can only be used at runtime, you can use this syntax at both compile time and runtime.
It is illegal to have both a stack trace suppression and a file/line suppression on the same line. For example:
suppress myerror {a b c} at foo.c:3
Suppressing Other Warning Messages
You can use the suppress_output
option for compile-time warning messages that do not have an associated number. This option takes a string as an argument and will suppress any message with text that matches the string. For example, the following option would suppress the warning from the previous section, as well as any others that included this text string:
insure++.suppress_output wrong arguments passed
Enabling Error Messages
You can enable currently-suppressed error messages by configuring the system default or your .psrc file. See Error Codes for more information.
Add the unsuppress
option to your .psrc file. The following example releases RETURN_FAILURE messages:
insure++.unsuppress RETURN_FAILURE
Report Summaries
Normally, you will see error messages for individual errors as your program proceeds. Using the other options described so far, you can enable or disable these errors or control the exact number seen at each source line. This technique is most often used to systematically track down each problem, one by one. However, it is often useful to obtain a summary of the problems remaining in a piece of code in order to track its progress. Insure++ supports the following types of summary reports:
- A bug summary which lists all outstanding bugs according to their error codes.
- A leak summary which lists all memory leaks - that is, places where memory is being permanently lost.
- An outstanding summary which lists all outstanding memory blocks - that is, places where memory is not being freed, but is not leaked because a valid pointer to the block still exists.
- A coverage summary which indicates how much of the application’s code has been executed.
Bugs Summary
You can include the this report summary by adding the insure++.summarize bugs
option to your .psrc file and re-running your program.
In addition to the normal error reports, you will then also see a summary such as the one shown below:
******************* INSURE SUMMARY *********v7.4***** * Program : hello * Arguments : this is bug summary test * Directory : /home/Insure++/examples/c * Compiled on : Mar 25, 2007 15:22:58 * Run on : Mar 26, 2007 13:16:43 * Elapsed time : 00:00:00 * Malloc HWM : 0 bytes ****************************************************** PROBLEM SUMMARY - by type =============== Problem Reported Suppressed ------------------------------------------------- READ_OVERFLOW 3 0 WRITE_OVERFLOW 2 1 ------------------------------------------------- TOTAL 5 1 ------------------------------------------------- PROBLEM SUMMARY - by location =============== READ_OVERFLOW: Reading overflows memory, 3 unique occurrences 1 at hello.c, 15 1 at hello.c, 16 1 at hello.c, 18 WRITE_OVERFLOW: Writing overflows memory, 2 unique occurrences 2 at hello.c, 15 1 at hello.c, 16
The INSURE SUMMARY section is a header that indicates the following information about the program being executed:
- The name of the program.
- Any command line arguments, if available.
- The directory from which the program was run.
- The time the program was compiled.
- The time the program was executed.
- The length of time needed to execute the program.
This information is provided so that test runs can be compared accurately as to the arguments and directory of test. The time and date information is supplied to correlate with bug tracking software.
The second section gives a summary of problems detected according to the error code and frequency. The first numeric column indicates the number of errors detected but not suppressed. This is the total number of errors, which might differ from the number reported, since, by default, only the first error of any particular type is reported at each source line. The second column indicates the number of bugs which were not displayed at all due to suppress
commands.
The third section gives details of the information presented in the second section, broken down into source files and line numbers.
Leak Summary
You can include the this report summary by adding the insure++.summarize leaks
option to your .psrc file and re-running your program.
The output indicates the memory (mis)use of the program, as shown below.
********************* INSURE SUMMARY ********* v7.4 ** * Program : leakscop * Arguments : * Directory : /home/Insure++/examples/c * Compiled on : Mar 26, 2007 13:15:27 * Run on : Mar 26, 2007 13:17:54 * Elapsed time : 00:00:00 * Malloc HWM : 10 bytes ****************************************************** PROBLEM SUMMARY - by type =============== Problem Reported Suppressed ------------------------------------------------- LEAK_SCOPE 1 0 ------------------------------------------------- TOTAL 1 0 ------------------------------------------------- PROBLEM SUMMARY - by location =============== LEAK_SCOPE: Memory leaked leaving scope, 1 unique occurrence 1 at leakscop.c, 10 MEMORY LEAK SUMMARY =================== 1 outstanding memory reference for 10 bytes. Leaks detected during execution ------------------------------- 10 bytes 1 chunk allocated at leakscop.c, 9 malloc() (interface) gimme() leakscop.c, 9 main() leakscop.c, 15 **************** INSURE SUMMARY ************** v7.4 ** Program : leak Arguments : Directory : C:\whicken\test Compiled on : Mar 12, 2007 15:09:05 Run on : Mar 12, 2007 15:09:31 Elapsed time : 00:00:02 ****************************************************** MEMORY LEAK SUMMARY =================== 4 outstanding memory references for 45 bytes. Leaks detected during execution ------------------------------- 10 bytes 1 chunk allocated at leak.c, 6 Leaks detected at exit ---------------------- 10 bytes 2 chunk allocated at leak.c, 7 Outstanding allocated memory ---------------------------- 15 bytes 1 chunk allocated at leak.c, 8
The first section summarizes the “memory leaks” which were detected during program execution, while the second lists leaked blocks that were detected at program exit. These are potentially serious errors, in that they typically represent continuously increasing use of system resources. If the program is “leaking” memory, it is likely to eventually exhaust the system resources and will probably crash.
The first number displayed is the total amount of memory lost at the indicated source line, and the second is the number of chunks of memory lost. Note that multiple chunks of different sizes may be lost at the same source line - depending on which options you are using.
To customize the report, there are three options available:
leak_combine
The leak_combine
option controls how Insure++ merges information about multiple blocks. The default behavior is to combine all information about leaks which were allocated from locations with identical stack traces (leak_combine trace
). It may be that you would rather combine all leaks based only on the file and line they were allocated, independent of the stack trace leading to that allocation. In that case, you would use leak_combine location
. Or, you may simply want one entry for each leak (leak_combine none
).
leak_sort
The leak_sort
option controls how the leaks are sorted after having been combined. The options are none
, location
, trace
, size
, and frequency
(size
is the default). Sorting by size lets you look at the biggest sources of leaks, sorting by frequency lets you look at the most often occurring source of leaks, and sorting by location provides an easy way to examine all your leaks.
leak_trace
The leak_trace
option causes a full stack trace of each allocation to be printed, in addition to the actual file and line where the allocation occurred.
The third section shows the blocks which are allocated to the program at its termination and which have valid pointers to them. Since the pointers allow the blocks to still be freed by the program (even though they are not), these blocks are not actually leaked. This section is only displayed if the outstanding keyword is used. Normally, these blocks do not cause problems, since the operating system will reclaim them when the program terminates. However, if your program is intended to run for extended periods, these blocks are potentially more serious.
Coverage Summary
You can include the this report summary by adding the insure++.summarize coverage
option to your .psrc file and re-running your program.
In addition to the normal error reports, the summary includes how much of the application's source code has been tested. The exact form of the output is controlled by the coverage_switches
option, which specifies the command line switches passed to the tca
command to create the output.
If this variable is not set, it defaults to the following setting:
insure++.coverage_switches tca -dS
The following example summary shows test coverage:
COVERAGE SUMMARY ================ 0 blocks untested 28 blocks tested 100% covered