discover 报告为您提供用于有效精确定位并修复源代码中的问题的信息。
缺省情况下,该报告以 HTML 格式写入 output-file.html,其中 output-file 是检测过的二进制文件的基名。该文件位于您运行检测过的二进制文件时所在的工作目录中。
检测二进制文件时,可以使用 –H 选项请求将 HTML 输出写入指定的文件,或使用 –w 选项请求将其写入文本文件。
检测二进制文件后,如果您希望将报告写入其他文件以便后续运行该程序,则可以通过 SUNW_DISCOVER_OPTIONS 环境变量为报告更改 –H 和 –w 选项的设置。 有关更多信息,请参见SUNW_DISCOVER_OPTIONS 环境变量。
使用 HTML 报告格式可以对程序进行交互分析。开发者可以通过使用电子邮件或者通过发布到 Web 页上来轻松共享 HTML 格式的数据。该格式与 JavaScript 交互式功能相结合,提供了一种在 discover 消息中导航的便捷方法。
本节介绍 HTML 报告,其中包含以下选项卡:
使用 "Errors"(错误)选项卡、"Warnings"(警告)选项卡和 "Memory Leaks"(内存泄漏)选项卡,可以分别在错误消息、警告消息和内存泄漏报告中导航。
使用左侧的控制面板,可以更改当前显示在右侧的选项卡的内容。请参见使用控制面板。
在浏览器中第一次打开 HTML 报告时,会选择 "Errors"(错误)选项卡,其中显示在检测过的二进制文件执行过程中发生的内存访问错误列表:
如果编译代码时使用了 –g 选项,则可以通过单击堆栈跟踪中的每个函数来查看相应函数的源代码:
"Warnings"(警告)选项卡显示了有关可能的访问错误的所有警告消息。单击某一条警告时,会显示发出该警告时的堆栈跟踪。 如果编译代码时使用了 –g 选项,则可以通过单击堆栈跟踪中的每个函数来查看相应函数的源代码:
"Memory Leaks"(内存泄漏)选项卡在顶部显示在程序运行结束时仍被分配的块的总数,并在下方列出这些块:
单击某个块时,会显示该块的堆栈跟踪。 如果编译代码时使用了 –g 选项,则可以通过单击堆栈跟踪中的每个函数来查看相应函数的源代码:
要查看所有错误、警告和内存泄漏的堆栈跟踪,请在控制面板的 "Stack Traces"(堆栈跟踪)部分中单击 "Expand All"(全部展开)。要查看所有函数的源代码,请在控制面板的 "Source Code"(源代码)部分中单击 "Expand All"(全部展开)。
要隐藏所有错误、警告和内存泄漏的堆栈跟踪或源代码,请单击相应的 "Collapse All"(全部折叠)。
选择相关的选项卡时,会显示控制面板的 "Show Errors"(显示错误)或 "Show Warnings"(显示警告)部分。缺省情况下,会选中所有检测到的错误或警告的选项。要隐藏某种类型的错误或警告,请将其取消选中。
控制面板的底部显示了报告摘要,其中列出了错误和警告总数,以及泄漏的内存量。
discover 报告的 ASCII(文本)格式适合由脚本进行处理或无法访问 Web 浏览器的情况。以下示例显示了一个 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)