You can use –-union to process multiple dynamic reports with codean. It can be used to display, save, show new issues, or show fixed issues, of results from running discover on a test suite. The following example shows how to use discover and codean -–union.
This will clean all existing dynamic reports under a.out.analyze/dynamic/.
By default, the result of each run saves in a separate file, and the latest report is a symbolic link to the most recent one. For example, this is how a.out.analyze/dynamic/ directory looks like after running a.out for 5 times:
$ ls -l a.out.analyze/dynamic/ total 11 lrwxrwxrwx 1 demoUser demo 18 May 1 15:14 latest -> ./latest.AAAvCaWri -rwxrwxrwx 1 demoUser demo 588 Apr 30 10:05 latest.AAACRaOId -rwxrwxrwx 1 demoUser demo 587 Apr 15 15:03 latest.AAAQcayId -rwxrwxrwx 1 demoUser demo 587 Apr 30 10:05 latest.AAAe5aWId -rwxrwxrwx 1 demoUser demo 587 Apr 15 15:03 latest.AAAlCaGId -rwxrwxrwx 1 demoUser demo 587 May 1 15:14 latest.AAAvCaWri
After you've prepared reports with discover, you can process all dynamic reports under a.out.analyze/dynamic/ using codean.
To display individual reports:
% codean --union -d a.out
The codean command processes all individual dynamic reports under a.out.analyze/dynamic in alphabetical order. It only produces text output (meaning no combined Analytics output or HTML output, unlike standard codean runs). For the same issue, no matter which reports are present, the detail of the issue is only shown at the first instance. For the rest of its appearances, codean will only display limited information, like the following:
LEAK 1: repeated, 1 blocks, 4 bytes ERROR 1: repeated 1 time
The discover information will only be shown once, at the end of the full report, to summarize issue counts in the whole test suite. The complete codean output of the example is as follows:
$ codean --union -d a.out Displaying dynamic report of a.out.analyze/dynamic/latest.AAACRaOId: ERROR 1 (UMR): accessing uninitialized data in "*i" at address 0x8090010 (4 bytes) on the heap at: main() + 0xe1 <hello.c : 10> 5: { 6: int *i = malloc(sizeof(int)); 8: int j = 0; 10:=> j = *i; 12: return 0; _start() + 0x71 was allocated at (4 bytes): main() + 0x5e <hello.c : 6> 2: #include <stdio.h> 4: int main() 5: { 6:=> int *i = malloc(sizeof(int)); 8: int j = 0; _start() + 0x71 Displaying dynamic report of a.out.analyze/dynamic/latest.AAAQcayId: LEAK 1: 1 allocation with total size of 4 bytes main() + 0x5e <hello.c : 6> 2: #include <stdio.h> 4: int main() 5: { 6:=> int *i = malloc(sizeof(int)); 8: int j = 0; _start() + 0x71 ERROR 1: repeated 1 time Displaying dynamic report of a.out.analyze/dynamic/latest.AAAe5aWId: LEAK 1: repeated, 1 blocks, 4 bytes ERROR 1: repeated 1 time Displaying dynamic report of a.out.analyze/dynamic/latest.AAAlCaGId: LEAK 1: repeated, 1 blocks, 4 bytes ERROR 1: repeated 1 time Displaying dynamic report of a.out.analyze/dynamic/latest.AAAvCaWri: LEAK 1: repeated, 1 blocks, 4 bytes ERROR 1: repeated 1 time DISCOVER SUMMARY for a.out: 1 non-leak issues, 1 leak issues unique errors : 1 (5 total) unique warnings : 0 (0 total) unique leaks : 1 (4 blocks, 16 bytes) unique possible leaks : 0 (0 blocks, 0 bytes)
Note that definite leaks and possible leaks are treated differently. For standard codean runs, whether a leak is a definite leak or a possible leak completely depends on the confidence value in the Analytics report. But for "test suite" codean runs, if a leak is a definite leak in any of the dynamic reports, it will also be identified as a definite leak in the rest of the reports, no matter the confidence value in these reports. See how LEAK 1 is presented in the following "test suite" codean and standard codean reports:
$ codean --union -d a.out Displaying dynamic report of a.out.analyze/dynamic/latest.AAACRaOId: ... Displaying dynamic report of a.out.analyze/dynamic/latest.AAAQcayId: LEAK 1: 1 allocation with total size of 4 bytes main() + 0x5e <hello.c : 6> 2: #include <stdio.h> 4: int main() 5: { 6:=> int *i = malloc(sizeof(int)); 8: int j = 0; _start() + 0x71 ... Displaying dynamic report of a.out.analyze/dynamic/latest.AAAe5aWId: LEAK 1: repeated, 1 blocks, 4 bytes ... Displaying dynamic report of a.out.analyze/dynamic/latest.AAAlCaGId: LEAK 1: repeated, 1 blocks, 4 bytes ... Displaying dynamic report of a.out.analyze/dynamic/latest.AAAvCaWri: LEAK 1: repeated, 1 blocks, 4 bytes ... DISCOVER SUMMARY for a.out: 1 non-leak issues, 1 leak issues unique errors : 1 (5 total) unique warnings : 0 (0 total) unique leaks : 1 (4 blocks, 16 bytes) unique possible leaks : 0 (0 blocks, 0 bytes) tests$ codean -d a.out DYNAMIC report of a.out: ... LEAK (Possible leak) 1: 1 allocation with total size of 4 bytes main() + 0x5e <hello.c : 6> 2: #include <stdio.h> 4: int main() 5: { 6:=> int *i = malloc(sizeof(int)); 8: int j = 0; _start() + 0x71 DISCOVER SUMMARY for a.out: 1 non-leak issues, 1 leak issues unique errors : 1 (1 total) unique warnings : 0 (0 total) unique leaks : 0 (0 blocks, 0 bytes) unique possible leaks : 1 (1 blocks, 4 bytes)
To save reports in a test suite:
% codean --save --union -d --tag run1 a.out
Each dynamic report under a.out.analyze/dynamic/ is saved in a separate file.
$ ls -l a.out.analyze/history/run1/ total 15 lrwxrwxrwx 1 demoUser demo 26 Sep 30 11:09 dynamic -> ./dynamic.latest.AAACRaOId -rw-r--r-- 1 demoUser demo 674 Sep 30 11:09 dynamic.latest.AAACRaOId -rw-r--r-- 1 demoUser demo 847 Sep 30 11:09 dynamic.latest.AAAQcayId -rw-r--r-- 1 demoUser demo 847 Sep 30 11:09 dynamic.latest.AAAe5aWId -rw-r--r-- 1 demoUser demo 847 Sep 30 11:09 dynamic.latest.AAAlCaGId -rw-r--r-- 1 demoUser demo 847 Sep 30 11:09 dynamic.latest.AAAvCaWri
To compare reports in a test suite:
% codean --whatisnew --union -d --tag run1 a.out % codean --whatisfixed --union -d --tag run1 a.out
The codean command shows the new and fixed issues of all dynamic reports that are currently under a.out.analyze/dynamic/ as a set, against all saved dynamic reports under a.out.analyze/history/run1/ as a set. The following is a sample output.
$ codean --whatisnew --union -d --tag run1 a.out DYNAMIC report of a.out showing new issues: New issues in a.out.analyze/dynamic/latest.AAARTaOxS: ERROR 1 (ABR): reading memory beyond array bounds at address 0xfeffdef8 (4 bytes) on the stack at: main() + 0x68 <hello.c : 11> 6: // int *i = malloc(sizeof(int)); 7: int i[30]; 9: int j = 0; 11:=> j = i[35]; 13: return 0; _start() + 0x71 New issues in a.out.analyze/dynamic/latest.AAATDaGxS: ERROR 1 is a new, but repeated error. It was first seen as ERROR 1 in latest.AAARTaOxS. New issues in a.out.analyze/dynamic/latest.AAArca4wS: ERROR 1 is a new, but repeated error. It was first seen as ERROR 1 in latest.AAARTaOxS. DISCOVER SUMMARY for a.out: 1 new non-leak issues, 0 new leak issues new unique errors : 1 (3 total) new unique warnings : 0 (0 total) new unique leaks : 0 (0 blocks, 0 bytes) new unique possible leaks : 0 (0 blocks, 0 bytes) tests$ codean --whatisfixed --union -d --tag run1 a.out DYNAMIC report of a.out showing fixed issues: Fixed issues in a.out.analyze/history/run1/dynamic.latest.AAACRaOId: ERROR 1 (UMR): accessing uninitialized data in "*i" at address 0x8090010 (4 bytes) on the heap at: (Warning: Source files have changed. Source code shown below may not be accurate.) main() + 0xe1 <hello.c : 10> 6: // int *i = malloc(sizeof(int)); 7: int i[30]; 9: int j = 0; 11: j = i[35]; _start() + 0x71 was allocated at (4 bytes): main() + 0x5e <hello.c : 6> 2: #include <stdio.h> 4: int main() 5: { 6:=> // int *i = malloc(sizeof(int)); 7: int i[30]; _start() + 0x71 Fixed issues in a.out.analyze/history/run1/dynamic.latest.AAAQcayId: ERROR 1 is a fixed, but repeated error. It was first seen as ERROR 1 in dynamic.latest.AAACRaOId. LEAK 1: 1 allocation with total size of 4 bytes (Warning: Source files have changed. Source code shown below may not be accurate.) main() + 0x5e <hello.c : 6> 2: #include <stdio.h> 4: int main() 5: { 6:=> // int *i = malloc(sizeof(int)); 7: int i[30]; _start() + 0x71 Fixed issues in a.out.analyze/history/run1/dynamic.latest.AAAe5aWId: ERROR 1 is a fixed, but repeated error. It was first seen as ERROR 1 in dynamic.latest.AAACRaOId. LEAK 1 is a fixed, but repeated leak. It was first seen as LEAK 1 in dynamic.latest.AAAQcayId. Fixed issues in a.out.analyze/history/run1/dynamic.latest.AAAlCaGId: ERROR 1 is a fixed, but repeated error. It was first seen as ERROR 1 in dynamic.latest.AAACRaOId. LEAK 1 is a fixed, but repeated leak. It was first seen as LEAK 1 in dynamic.latest.AAAQcayId. Fixed issues in a.out.analyze/history/run1/dynamic.latest.AAAvCaWri: ERROR 1 is a fixed, but repeated error. It was first seen as ERROR 1 in dynamic.latest.AAACRaOId. LEAK 1 is a fixed, but repeated leak. It was first seen as LEAK 1 in dynamic.latest.AAAQcayId. DISCOVER SUMMARY for a.out: 1 fixed non-leak issues, 1 fixed leak issues fixed unique errors : 1 (5 total) fixed unique warnings : 0 (0 total) fixed unique leaks : 1 (4 blocks, 16 bytes) fixed unique possible leaks : 0 (0 blocks, 0 bytes)