There are several discover APIs and environment variables that you can specify in your code.
Oracle Solaris Studio 12.4 implements six new discover functions that you can call from your program to receive memory leak and memory allocation information. These functions print the information on stderr. At the end of the program output, discover by default prints the final memory report with the memory leaks in the program. To use these APIs, the source file of the application needs to include the header file for discover: #include <discoverAPI.h>.
The functions and what they report are as follows:
Reports all memory allocations
Reports all memory allocations not previously reported.
Marks all memory allocations thus far as reported.
Reports all memory leaks.
Reports all memory leaks not previously reported.
Marks all memory leaks thus far as reported
This section describes some methods for working with discover APIs.
For each function specified in your code, discover reports the stack of where the memory was allocated. Memory leaks are allocated memory that is unreachable in the program.
The following example shows how to use these APIs:
$ 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
The following example shows the expected output.
******** 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(); _start() + ********************************************************** ******** 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; _start() + 0x71 ********************************************************** ***************** 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(); _start() + 0x71 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; _start() + 0x71 DISCOVER SUMMARY: unique errors : 0 (0 total) unique warnings : 0 (0 total)
If you have a long-running program or a server that never exits, you can call these discover functions using dbx at any time, even if you have not put the calls in your code. The program must have been run with at least the light mode of discover using the –l option. Note that dbx can attach to a running program. The following example shows how to find leaks in a long-running program.
Example 1 Finding Two Leaks in a Long Running ProgramFor this example, the a.out file is a long-running program with two processes, each with one leak. Each process is assigned a process ID.
The following rl script contains the commands to ask the program to report unreported memory leaks.
#!/bin/sh dbx - $1 > /dev/null 2> &1 << END call discover_report_unreported_leaks() exit END
Once you have a program and a script, you can use discover and run the program.
% discover -l -w - a.out % a.out 8252: Parent allocation 64 8253: Child allocation 32
In a separate terminal window, you can run the script on the parent process.
% rl 8252
The program reports the following information for the parent process:
******** 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); _start() + 0x66 **********************************************************
Run the script again for the child process.
% rl 8253
The program reports the following information for the child process:
******** 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); _start() + 0x66 **********************************************************
You can use the script repeatedly to find any new leaks.
You can change the runtime behavior of an instrumented binary by setting the SUNW_DISCOVER_OPTIONS environment variable to a list of the command-line options –a, –A, –b, –e, –E, –f, –F, –H, –l, –L, –m, –P, –S, and –w. For example, if you want to change the number of errors reported to 50 and limit the stack depth in the report to 3, you would set the environment variable to the following:.
–e 50 –s 3
By default, if a binary you have instrumented with discover forks while you are running it, discover continues to collect memory access error data from the parent and child processes, meaning the default behavior is both. For example. if you want discover to follow the fork and collect memory access data from the child process, set the SUNW_DISCOVER_FOLLOW_FORK_MODE environment variable to:
–F child