Oracle Solaris Studio 12.2 Discover 和 Uncover 用户指南

分析 ASCII 报告

按脚本进行处理时,或者无权访问 Web 浏览器时,适合使用 ASCII(文本)格式的 Discover 报告。下面是 ASCII 报告的一个示例。


$ a.out

ERROR 1 (UAW): writing to unallocated memory at address 0x50088 (4 bytes) at:
   main() + 0x2a0  <ui.c:20>
       17:     t = malloc(32);
       18:     printf("hello\n");
       19:     for (int i=0; i<100;i++)
       20:=>    t[32] = 234; // UAW
       21:     printf("%d\n", t[2]);   //UMR
       22:     foo();
       23:     bar();
   _start() + 0x108
ERROR 2 (UMR): accessing uninitialized data from address 0x50010 (4 bytes) at:
   main() + 0x16c  <ui.c:21>$
       18:     printf("hello\n");
       19:     for (int i=0; i<100;i++)
       20:      t[32] = 234; // UAW
       21:=>   printf("%d\n", t[2]);   //UMR
       22:     foo();
       23:     bar();
       24:    }
   _start() + 0x108
       was allocated at (32 bytes):
   main() + 0x24  <ui.c:17>
       14:     x = (int*)malloc(size); // AZS warning
       15:    }
       16:    int main() {
       17:=>   t = malloc(32);
       18:     printf("hello\n");
       19:     for (int i=0; i<100;i++)
       20:      t[32] = 234; // UAW
   _start() + 0x108
0
WARNING 1 (AZS): allocating zero size memory block at:
   foo() + 0xf4  <ui.c:14>
       11:    void foo() {
       12:     x = malloc(128);
       13:     free(x);
       14:=>   x = (int*)malloc(size); // AZS warning
       15:    }
       16:    int main() {
       17:     t = malloc(32);
   main() + 0x18c  <ui.c:22>
       19:     for (int i=0; i<100;i++)
       20:      t[32] = 234; // UAW
       21:     printf("%d\n", t[2]);   //UMR
       22:=>   foo();
       23:     bar();
       24:    }
   _start() + 0x108

***************** Discover Memory Report *****************

1 block at 1 location left allocated on heap with a total size of 128 bytes

   1 block with total size of 128 bytes
   bar() + 0x24  <ui.c:9>
       6:           7:    void bar() {
        8:     int *y;
        9:=>   y = malloc(128);  // Memory leak
       10:    }
       11:    void foo() {
       12:     x = malloc(128);
   main() + 0x194  <ui.c:23>
       20:      t[32] = 234; // UAW
       21:     printf("%d\n", t[2]);   //UMR
       22:     foo();
       23:=>   bar();
       24:    }
   _start() + 0x108

ERROR 1: repeats 100 times
DISCOVER SUMMARY:
   unique errors   : 2 (101 total, 0 filtered)
   unique warnings : 1 (1 total, 0 filtered)

该报告包括错误和警告消息,其后是摘要。

错误消息以 ERROR 一词开头,并包含一个三字母代码、一个 ID 编号以及错误描述(本例中为 writing to unallocated memory)。其他详细信息包括访问的内存地址,以及读取或写入的字节数。在描述的后面,是发生错误时的栈跟踪,可以根据栈跟踪在进程生命周期中定位错误的位置。

如果程序是使用 -g 选项编译的,栈跟踪将包括源文件名称和行号。如果源文件可访问,则输出错误位置附近的源代码。每一帧中的目标源代码行均以符号 => 表示。

如果同一内存位置重复出现字节数相同的同一错误类型,完整的消息(包括栈跟踪)仅输出一次。对于多次出现的每个相同错误,会统计后续的错误,并在报告的末尾列出重复计数(如下例中所示)。


ERROR 1: repeats 100 times

如果出错内存访问的地址位于堆上,则在栈跟踪的后面输出相应堆块的信息。这些信息包括块的起始地址和大小,以及分配该块时的栈跟踪。如果该块已释放,将还包括解除分配点的栈跟踪。

警告消息的输出格式与错误消息相同,只不过是以 WARNING 一词开头。一般来说,这些消息只是提醒您注意那些不会影响应用程序正确性的情况,但提供的有用信息可帮助您改进程序。例如,分配大小为零的内存不会造成损害,但如果经常这样做可能会降低性能。

内存泄漏报告包含有关在堆上分配的、但程序退出时未释放的内存块的信息。下面是内存泄漏报告的一个示例。


$ DISCOVER_MEMORY_LEAKS=1 ./a.out
...
***************** Discover Memory Report *****************

2 blocks left allocated on heap with total size of 44 bytes
    block at 0x50008 (40 bytes long) was allocated at:
        malloc() + 0x168 [libdiscover.so:0xea54]
        f() + 0x1c [a.out:0x3001c]
          <discover_example.c:9>:
                 8:    {
                 9:=>    int *a = (int *)malloc( n * sizeof(int) );
                10:      int i, j, k;
        main() + 0x1c [a.out:0x304a8]
          <discover_example.c:33>:
                32:      /* Print first N=10 Fibonacci numbers */
                33:=>    a = f(N);
                34:      printf("First %d Fibonacci numbers:\n", N);
        _start() + 0x5c [a.out:0x105a8]
...

标题下面的第一行汇总了在堆上保持已分配状态的堆块数及其总大小。报告的大小是从开发人员的立场提供的,也就是说,不包括内存分配器的簿记系统开销。

内存泄漏摘要的后面输出了每个未释放堆块及其分配点栈跟踪的详细信息。该栈跟踪报告类似于前面介绍错误和警告消息时提到的栈跟踪报告。

Discover 报告的结尾是总摘要。该摘要报告了唯一警告和错误的数目,并在括号中提供了错误和警告的总数(包括重复项)。例如:


DISCOVER SUMMARY:
        unique errors   : 3 (3 total)
        unique warnings : 1 (5 total)