Oracle® Developer Studio 12.5:Discover 和 Uncover 用户指南

退出打印视图

更新时间: 2016 年 6 月
 
 

discover API 和环境变量

有多个可供在代码中指定的 discover API 和环境变量。

discover API

Oracle Developer Studio 12.5 实现了六个新的可以从程序调用以接收内存泄漏和内存分配信息的 discover 函数。这些函数将信息输出到 stderr。缺省情况下,discover 会在程序输出的末尾输出包含程序中内存泄漏的最终内存报告。要使用这些 API,应用程序的源文件需要包含 discover 的头文件:#include <discoverAPI.h>

这些函数及其报告的内容如下所示:

discover_report_all_inuse()

报告所有内存分配。

discover_report_unreported_inuse()

报告以前未报告的所有内存分配。

discover_mark_all_inuse_as_reported()

将迄今为止的所有内存分配标记为已报告。

discover_report_all_leaks()

报告所有内存泄漏。

discover_report_unreported_leaks()

报告以前未报告的所有内存泄漏。

discover_mark_all_leaks_as_reported()

将迄今为止的所有内存泄漏标记为已报告。

本节介绍一些使用 discover API 的方法。


注 -  discover API 在 ADI 模式下不起作用。

使用 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 环境变量

您可以通过将 SUNW_DISCOVER_OPTIONS 环境变量设置为命令行选项 –a–A–b–e–E–f–F–H–l–L–m–P–S–w 的列表来更改检测过的二进制文件的运行时行为。例如,如果您希望将报告的错误数更改为 50 并将报告中的堆栈深度限制为 3,则可以按以下方式设置环境变量:

–e 50 –S 3