コード内に指定できる discover API と環境変数がいくつか用意されています。
Oracle Developer Studio 12.5 には、プログラムから呼び出してメモリーリークやメモリー割り当ての情報を受け取ることができる 6 つの新しい 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 長時間実行プログラム内の 2 つのリークの検出この例で、a.out ファイルは 2 つのプロセスを持つ長時間実行プログラムであり、各プロセスにリークが 1 つずつあります。各プロセスにはプロセス 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