有多个可供在代码中指定的 discover API 和环境变量。
Oracle Developer Studio 12.5 实现了六个新的可以从程序调用以接收内存泄漏和内存分配信息的 discover 函数。这些函数将信息输出到 stderr。缺省情况下,discover 会在程序输出的末尾输出包含程序中内存泄漏的最终内存报告。要使用这些 API,应用程序的源文件需要包含 discover 的头文件:#include <discoverAPI.h>。
这些函数及其报告的内容如下所示:
报告所有内存分配。
报告以前未报告的所有内存分配。
将迄今为止的所有内存分配标记为已报告。
报告所有内存泄漏。
报告以前未报告的所有内存泄漏。
将迄今为止的所有内存泄漏标记为已报告。
本节介绍一些使用 discover API 的方法。
对于在您的代码中指定的每个函数,discover 会报告内存分配位置的堆栈。内存泄漏是在程序中无法访问的已分配内存。
以下示例显示如何使用这些 API:
$ cat -n tdata.C
1 #include <discoverAPI.h>
2
3 void foo()
4 {
5 int *j = new int;
6 }
7
8 int main()
9 {
10 foo();
11 discover_report_all_leaks();
12
13 foo();
14 discover_report_unreported_leaks();
15
16 return 0;
17 }
$ CC -g tdata.C
$ discover -w - a.out
$ a.out
以下示例显示了预期输出。
******** discover_report_all_leaks() Report ********
1 allocation at 1 location left on the heap with a total size of 4 bytes
LEAK 1: 1 allocation with total size of 4 bytes
void*operator new(unsigned) + 0x36
void foo() + 0x5e <tdata.C:5>
2:
3: void foo()
4: {
5:=> int *j = new int;
6: }
7:
8: int main()
main()+0x1a <tdata.C:10>
9: {
10:=> foo();
11: discover_report_all_leaks();
12:
13: foo();
**********************************************************
******** discover_report_unreported_leaks() Report ********
1 allocation at 1 location left on the heap with a total size of 4 bytes
LEAK 1: 1 allocation with total size of 4 bytes
void*operator new(unsigned) + 0x36
void foo() + 0x5e <tdata.C:5>
2:
3: void foo()
4: {
5:=> int *j = new int;
6: }
7:
8:int main()
main() + 0x24 <tdata.C:13>
10: foo();
11: discover_report_all_leaks();
12:
13:=> foo();
14: discover_report_unreported_leaks();
15:
16:return 0;
**********************************************************
***************** Discover Memory Report *****************
2 allocations at 2 locations left on the heap with a total size of 8 bytes
LEAK 1: 1 allocation with total size of 4 bytes
void*operator new(unsigned) + 0x36
void foo() + 0x5e <tdata.C:5>
2:
3: void foo()
4: {
5:=> int *j = new int;
6: }
7:
8: int main()
main() + 0x1a <tdata.C:10>
7:
8: int main()
9: { 10:=> foo();
11: discover_report_all_leaks();
12:
13: foo();
LEAK 2: 1 allocation with total size of 4 bytes
void*operator new(unsigned) + 0x36
void foo() + 0x5e <tdata.C:5>
2:
3: void foo()
4: {
5:=> int *j = new int;
6: }
7:
8: int main()
main() + 0x24 <tdata.C:13>
10: foo();
11: discover_report_all_leaks();
12:
13:=> foo();
14: discover_report_unreported_leaks();
15:
16: return 0;
DISCOVER SUMMARY:
unique errors : 0 (0 total)
unique warnings : 0 (0 total)
如果您有长期运行的程序或从不退出的服务器,则可以随时使用 dbx 调用这些 discover 函数,即使您未将调用放置在代码中也可以执行此操作。必须至少已使用 –l 选项以 discover 的轻量模式运行了该程序。请注意,dbx 可以附加到正在运行的程序。以下示例显示如何在长期运行的程序中查找泄漏
示例 2 在长期运行的程序中找到两处泄漏对于本示例,a.out 文件是长期运行的具有两个进程的程序,每个进程存在一处泄漏。为每个进程分配了一个进程 ID。
以下 rl 脚本包含用于指示程序报告尚未报告的内存泄漏的命令。
#!/bin/sh dbx - $1 > /dev/null 2> &1 << END call discover_report_unreported_leaks() exit END
一旦您具有程序和脚本,就可以使用 discover 并运行该程序。
% discover -l -w - a.out % a.out 8252: Parent allocation 64 8253: Child allocation 32
在单独的终端窗口中,可以对父进程运行脚本。
% rl 8252
程序针对父进程报告以下信息:
******** discover_report_unreported_leaks() Report ********
1 allocation at 1 location left on the heap with a total size of 64 bytes
LEAK 1: 1 allocation with total size of 64 bytes
main() + 0x1e <xx.c:17>
14:
15: if (child > 0) {
16:
17:=> void *p = malloc(64);
18: printf("%jd: Parent allocation 64\n", (intmax_t)getpid());
19: p = 0;
20: for (int j=0; j < 1000; j++) sleep(1);
**********************************************************
针对子进程再次运行脚本。
% rl 8253
程序针对子进程报告以下信息:
******** discover_report_unreported_leaks() Report ********
1 allocation at 1 location left on the heap with a total size of 32 bytes
LEAK 1: 1 allocation with total size of 32 bytes
main() + 0x80 <xx.c:24>
21: }
22:
23: else {
24:=> void *p = malloc(32);
25: printf("%jd: Child allocation 32\n", (intmax_t)getpid());
26: p = 0;
27: for (int j=0; j < 1000; j++) sleep(1);
**********************************************************
可以重复使用脚本查找任何新的泄漏。
您可以通过将 SUNW_DISCOVER_OPTIONS 环境变量设置为命令行选项 –a、–A、–b、–e、–E、–f、–F、–H、–l、–L、–m、–P、–S 和 –w 的列表来更改检测过的二进制文件的运行时行为。例如,如果您希望将报告的错误数更改为 50 并将报告中的堆栈深度限制为 3,则可以按以下方式设置环境变量:
–e 50 –S 3