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

By default, error reports are sent to the Insra GUI. See Viewing Results for information viewing and navigating reports output to Insra. 

You can also output the report to a file by setting the report_file property either in the Advanced Settings screen or in the project Configuration Options (psrc) file. The setting supports filename tokens, such as %d, %p, or %V, so that you can define a report file template and keep track of the reports from multiple runs of your code. See Filenames for additional information about using filename tokens.

The following example generates a report file with name of the executable, followed by -err. and the date of the execution:

report_file %v-errs.%D

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.

The following example shows a READ_OVERFLOW error reported by Insure++:

[mainfrm.cpp:52] (Thread 0) **READ_OVERFLOW**
>>     d = var2->y;                       // READ_OVERFLOW

  Structure reference out of range: var2

          bbbbb
          | 4 | 4 |  8   |
                  rrrrrrrr

   Reading    (r) : 0x0000000000597548 thru 0x000000000059754f (8 bytes)
   From block (b) : 0x0000000000597540 thru 0x0000000000597543 (4 bytes)
                   var1, allocated at:
                          malloc()  (interface)
  mfc140u.dll 0x00007ff8099cd345()
                      CMainFrame()  mainfrm.cpp, 50
            CEdApp::InitInstance()  editor_demo.cpp, 45
  mfc140u.dll 0x00007ff809bf3574()
          __scrt_common_main_seh()  exe_common.inl, 288
             BaseThreadInitThunk()
              RtlUserThreadStart()

  Stack trace where the error occurred:
                      CMainFrame()  mainfrm.cpp, 52
            CEdApp::InitInstance()  editor_demo.cpp, 45
  mfc140u.dll 0x00007ff809bf3574()
          __scrt_common_main_seh()  exe_common.inl, 288
             BaseThreadInitThunk()
              RtlUserThreadStart()

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:

[mainfrm.cpp:52] (Thread 0) **READ_OVERFLOW** 

You can customize the output by setting the error_format option in your the Advanced Settings field or in the .psrc file. This enables you to format errors so that, for example, your IDE can search for the correct file and line number for each error.

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 advanced configuration options or .psrc file.

For example, the following format includes a timestamp in the generated report:

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. You can specify a value for the report_limit option, either in the Advanced options in the Insure++ Control Panel or directly in the .prsc file, to specify how many times additional errors are displayed. For example:

report_limit 1

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.

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 use the source_path option in your  advanced configuration or .prsc file to provide Insure++ with an alternative list of directories to search for source code:

source_path .;c:\users\boswell\src;c:\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. You can suppress errors in using the GUI (see Suppressions) or add the suppress option to your .psrc file and specify the error codes you want to suppress. For example:

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:

suppress LEAK_*

You can also suppress all errors, which will only create an error summary:

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:

suppress BAD_FORMAT(sign, compatible)

Alternatively, the following option would suppresses all sub-categories of the specified error class: 

suppress BAD_FORMAT

The next time you run the program, the specified errors will be suppressed in the reports.

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 (Windows):

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:

suppress all { * X* * } 
suppress all { * _X* * }

This suppresses errors in any function (or its descendants) that begins with either of the two sequences.

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:

suppress_output wrong arguments passed 

Enabling Error Messages

You can enable currently-suppressed error messages by configuring the system default, advanced configuration options 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:  

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:

  • Problem summary: Lists all outstanding bugs according to their error codes.
  • Leak summary: Lists all places where memory is permanently lost.
  • Outstanding summary: Lists all places where memory is not freed, but is not leaked because a valid pointer to the block still exists.
  • Coverage summary:Indicates how much of the application’s code has been executed.

The following example shows the main Insure++ report header.

************************* INSURE SUMMARY *********************** v2021.1 **
*   Program      : Editor_demo                                            *
*   Arguments    : Not available                                          *
*   Directory    : C:\Users\a\Documents\editor_demo\Insurex64\Debug       *
*   Compiled on  : Mar 04, 2021  09:15:51                                 *
*   Run on       : Apr 29, 2021  13:53:04                                 *
*   Elapsed time : 00:01:05                                               *
*   Malloc HWM   : 692205 bytes (675K)                                    *
***************************************************************************

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.

Problem Summary

You can include the this report summary by either enabling the Bugs option in the Summarize section of the Insure++ Control Panel (see Enabling the Problem Summary Report) or adding the summarize bugs option to your .psrc file.  

The following example shows a Problem summary exported to file:

PROBLEM SUMMARY - by type
===============

          Problem                Reported      Suppressed
          -------------------------------------------------
          ALLOC_CONFLICT               1                0
          DELETE_MISMATCH              1                1
          LEAK_ASSIGN                  2                1
          LEAK_SCOPE                   2                0
          READ_DANGLING                1                0
          READ_OVERFLOW                1                0
          READ_UNINIT_MEM              1                0
          -------------------------------------------------
          TOTAL                        9                2
          -------------------------------------------------

PROBLEM SUMMARY - by location
===============

ALLOC_CONFLICT: Memory allocation conflict, 1 unique occurrence
         1 at funcs.cpp, 6

DELETE_MISMATCH: Inconsistent usage of delete operator, 1 unique occurrence
         2 at funcs.cpp, 12

LEAK_ASSIGN: Memory leaked due to pointer reassignment, 2 unique occurrences
         1 at mainfrm.cpp, 86
         2 at testdll1.cpp, 64

LEAK_SCOPE: Memory leaked leaving scope, 2 unique occurrences
         1 at mainfrm.cpp, 87
         1 at testdll1.cpp, 21

READ_DANGLING: Reading from a dangling pointer, 1 unique occurrence
         1 at testdll1.cpp, 50

READ_OVERFLOW: Reading overflows memory, 1 unique occurrence
         1 at mainfrm.cpp, 52

READ_UNINIT_MEM: Reading uninitialized memory, 1 unique occurrence
         1 at testdll1.cpp, 50

The PROBLEM SUMMARY by type section gives a summary of problems detected according to the error code and frequency. It includes the number of reported errors and the number of suppressed errors. 

The PROBLEM SUMMARY by location section provides details about the information presented in the previous section, including source files and line numbers.

Refer to the Finding Bugs for additional information, including viewing the report in the GUI.

Leak Summary

You can include the this report summary by enabling the Leaks option in the Summarize section of the Insure++ Control Panel (see Enabling the Leak Summary Report) or by adding the summarize leaks option to your .psrc file.   

The following example shows the memory misuses of a program:

MEMORY LEAK SUMMARY
===================
3 outstanding memory references for 360 bytes (1K).

Leaks detected at exit
----------------------
       228 bytes 1 chunk allocated
                      LocalAlloc()  (interface)
                         StrDupW()
windows.storage.dll 0x00007ff839ad255c()
windows.storage.dll 0x00007ff839ad2499()
windows.storage.dll 0x00007ff839ad398c()
windows.storage.dll 0x00007ff839ad384f()
windows.storage.dll 0x00007ff839ad33ad()
windows.storage.dll 0x00007ff839ad17ed()
   SHCORE.dll 0x00007ff83cc84206()
    ntdll.dll 0x00007ff83e17fbd3()
    ntdll.dll 0x00007ff83e16315a()
             BaseThreadInitThunk()
              RtlUserThreadStart()

       100 bytes 1 chunk allocated
                      LocalAlloc()  (interface)
                         StrDupW()
windows.storage.dll 0x00007ff839ad2570()
windows.storage.dll 0x00007ff839ad2499()
windows.storage.dll 0x00007ff839ad398c()
windows.storage.dll 0x00007ff839ad384f()
windows.storage.dll 0x00007ff839ad33ad()
windows.storage.dll 0x00007ff839ad17ed()
   SHCORE.dll 0x00007ff83cc84206()
    ntdll.dll 0x00007ff83e17fbd3()
    ntdll.dll 0x00007ff83e16315a()
             BaseThreadInitThunk()
              RtlUserThreadStart()

        32 bytes 1 chunk allocated
                      LocalAlloc()  (interface)
                         StrDupW()
windows.storage.dll 0x00007ff839ad4380()
windows.storage.dll 0x00007ff839ad2585()
windows.storage.dll 0x00007ff839ad2499()
windows.storage.dll 0x00007ff839ad398c()
windows.storage.dll 0x00007ff839ad384f()
windows.storage.dll 0x00007ff839ad33ad()
windows.storage.dll 0x00007ff839ad17ed()
   SHCORE.dll 0x00007ff83cc84206()
    ntdll.dll 0x00007ff83e17fbd3()
    ntdll.dll 0x00007ff83e16315a()
             BaseThreadInitThunk()
              RtlUserThreadStart()

Outstanding allocated memory
----------------------------
       418 bytes      2 chunks allocated
                      LocalAlloc()  (interface)
                         StrDupW()
windows.storage.dll 0x00007ff839ad255c()
windows.storage.dll 0x00007ff839ad2499()
windows.storage.dll 0x00007ff839ad398c()
windows.storage.dll 0x00007ff839ad384f()
windows.storage.dll 0x00007ff839ad33ad()
windows.storage.dll 0x00007ff839ad17ed()
   SHCORE.dll 0x00007ff83cc84206()
    ntdll.dll 0x00007ff83e17fbd3()
    ntdll.dll 0x00007ff83e16315a()
             BaseThreadInitThunk()
              RtlUserThreadStart()

       200 bytes      2 chunks allocated
                      LocalAlloc()  (interface)
                         StrDupW()
windows.storage.dll 0x00007ff839ad2570()
windows.storage.dll 0x00007ff839ad2499()
windows.storage.dll 0x00007ff839ad398c()
windows.storage.dll 0x00007ff839ad384f()
windows.storage.dll 0x00007ff839ad33ad()
windows.storage.dll 0x00007ff839ad17ed()
   SHCORE.dll 0x00007ff83cc84206()
    ntdll.dll 0x00007ff83e17fbd3()
    ntdll.dll 0x00007ff83e16315a()
             BaseThreadInitThunk()
              RtlUserThreadStart()

        54 bytes 1 chunk allocated
                      LocalAlloc()  (interface)
                         StrDupW()
windows.storage.dll 0x00007ff839bc82ff()
windows.storage.dll 0x00007ff839ad2499()
windows.storage.dll 0x00007ff839ad398c()
windows.storage.dll 0x00007ff839ad384f()
windows.storage.dll 0x00007ff839ad33ad()
windows.storage.dll 0x00007ff839ad17ed()
   SHCORE.dll 0x00007ff83cc84206()
    ntdll.dll 0x00007ff83e17fbd3()
    ntdll.dll 0x00007ff83e16315a()
             BaseThreadInitThunk()
              RtlUserThreadStart()

The first section summarizes the memory leaks detected during program execution.

The second section lists leaked blocks that were detected at program exit. These are potentially serious errors because 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.

Outstanding Memory

The third section describes outstanding allocated memory blocks, which are blocks allocated to the program at its termination that have valid pointers to them. Because the pointers allow the blocks to be freed by the program--even though they are not--they are not actually leaked.

This section is generated if the Outstanding option was enabled. You can enable the outstanding allocated memory report in the Summarize section of the Insure++ Control Panel or by adding the summarize outstanding option to your .psrc file. Outstanding memory blocks do not normally cause problems because 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.

Refer to the Monitoring Memory Leaks chapter for additional information, including viewing the report in the GUI.

Customizing the Leak Summary Report

You can use the following options to customize the report. 

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.

Coverage Summary

You can include the this report summary by enabling the Coverage option in the Summarize section of the Control Panel or by adding the summarize coverage option to your .psrc file. 

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:

coverage_switches tca -dS

The following example summary shows test coverage: 

COVERAGE SUMMARY
================
	0 blocks untested
	28 blocks tested

100% covered

Refer to the Code Coverage chapter for details about collecting and analyzing code coverage.

  • No labels