Mandalika's scratchpad [ Work blog @Oracle | Stock Market Notes | My Music Compositions ]

Old Posts: 09.04  10.04  11.04  12.04  01.05  02.05  03.05  04.05  05.05  06.05  07.05  08.05  09.05  10.05  11.05  12.05  01.06  02.06  03.06  04.06  05.06  06.06  07.06  08.06  09.06  10.06  11.06  12.06  01.07  02.07  03.07  04.07  05.07  06.07  08.07  09.07  10.07  11.07  12.07  01.08  02.08  03.08  04.08  05.08  06.08  07.08  08.08  09.08  10.08  11.08  12.08  01.09  02.09  03.09  04.09  05.09  06.09  07.09  08.09  09.09  10.09  11.09  12.09  01.10  02.10  03.10  04.10  05.10  06.10  07.10  08.10  09.10  10.10  11.10  12.10  01.11  02.11  03.11  04.11  05.11  07.11  08.11  09.11  10.11  11.11  12.11  01.12  02.12  03.12  04.12  05.12  06.12  07.12  08.12  09.12  10.12  11.12  12.12  01.13  02.13  03.13  04.13  05.13  06.13  07.13  08.13  09.13  10.13  11.13  12.13  01.14  02.14  03.14  04.14  05.14  06.14  07.14  09.14  10.14  11.14  12.14  01.15  02.15  03.15  04.15  06.15  09.15  12.15  01.16  03.16  04.16  05.16  06.16  07.16  08.16  09.16  12.16  01.17  02.17  03.17 


Sunday, March 13, 2005
 
Sun Studio: Investigating memory leaks with Collector/Analyzer

Sun Studio compiler collection bundles a set of tools for collecting and analyzing performance data from an application. Collector & Analyzer, a pair of tools from Sun Studio suite that we use to collect and analyze the performance data. Both tools can be used from the command line or from a graphical user interface.

These two tools help answering the following questions:But this blog post mainly concentrates on finding memory leaks from the following simple C program

% more mem.c
#include <stdlib.h>
#include <stdio.h>

void allocate() {
int *x;
char *y;

x = (int *) malloc(sizeof(int) * 100);
y = (char *) malloc (sizeof(char) * 200);

printf("\nAddress of x = %u, y = %u", x, y);

x = (int *) malloc (sizeof(int) * 25);
y = (char *) malloc (sizeof(char) * 25);

printf("\nNew address of x = %u, y = %u\n", x, y);
free (y);
}

int main() {
allocate();
return (0);
}

From the code, it is clear that the program is requesting memory allocations four times (a total of 725 bytes); but releasing only 25 bytes from virtual memory. The following steps explain how to find this 700 byte leak with Collector/Analyzer.

  1. Prepare the program for data collection

    To see source code in annotated source and disassembly, and source lines in the line analysis, the source file must be compiled with -g compiler option to generate debug symbol information
    % CC -g -o mem mem.c

  2. Collect the data

    We can collect run-time data that is useful for later analysis by running the executable under collect utility. To see the entire list of arguments that collect accepts, type collect without any arguments on the command line. Since we were interested in memory leaks, we have to turn the heap tracing on with -H option. (By default, heap tracing is off). Also we have to supply an experiment name to hold the data with -o option
    % which collect
    /opt/SUNWspro/prod/bin/collect

    % collect -H on -o mem.er mem
    Creating experiment database mem.er ...

    Address of x = 134743584, y = 134743992
    New address of x = 134744200, y = 134614672


    It creates the mem.er experiment and archives the binary files describing each load object referenced in the loadobjects file
  3. Finally invoke the performance analyzer, er_print (command line tool) or analyzer (graphical tool)
    % er_print mem.er
    (er_print) source allocate
    Source file: ./mem.c
    Object file: ./mem
    Load Object: ./mem

    Incl. Incl. Excl. Incl.
    Bytes Leaks User CPU User CPU
    Leaked sec. sec.
    1. #include <stdlib.h>
    2. #include <stdio.h>
    3.
    0 0 0. 0. 4. void allocate() {

    0 0 0. 0. 5. int *x;
    0 0 0. 0. 6. char *y;
    7.
    400 1 0. 0. 8. x = (int *) malloc(sizeof(int) * 100);
    200 1 0. 0. 9. y = (char *) malloc (sizeof(char) * 200);
    10.
    0 0 0. 0. 11. printf("\nAddress of x = %u, y = %u", x, y);
    12.
    100 1 0. 0. 13. x = (int *) malloc (sizeof(int) * 25);
    0 0 0. 0. 14. y = (char *) malloc (sizeof(char) * 25);
    15.
    0 0 0. 0. 16. printf("\nNew address of x = %u, y = %u\n", x, y);
    0 0 0. 0. 17. free (y);
    0 0 0. 0. 18. }
    19.
    0 0 0. 0. 20. int main() {

    ## 700 3 0. 0. 21. allocate();
    0 0 0. 0. 22. return (0);
    0 0 0. 0. 23. }


    source allocate shows the annotated source with line numbers and number of bytes leaked from each line since we collected the data with heap tracing on (otherwise it shows the total CPU time spent in each line, by default)

    From the annotated source, we can see that 700 bytes were leaked after the execution of line:
    ## 700     3      0.        0.              21.         allocate();
    . And from the source of allocate(), the following lines were the culprits:

    400 1 0. 0. 8. x = (int *) malloc(sizeof(int) * 100);
    200 1 0. 0. 9. y = (char *) malloc (sizeof(char) * 200);
    100 1 0. 0. 13. x = (int *) malloc (sizeof(int) * 25);
    ____________

    0 0 0. 0. 14. y = (char *) malloc (sizeof(char) * 25);
    statement was clean, since we have 0 0 0. 0. 17. free (y); at the end of function allocate().

    We can also get much useful information with the help of leaks and allocs commands that relate to memory allocations and deallocations. Brief description of those commands are as follows:
    • leaks

      Display a list of memory leaks, aggregated by common call stack. Each entry presents the total number of leaks and the total bytes leaked for the given call stack. The list is sorted by the number of bytes leaked.

    • allocs

      Display a list of memory allocations, aggregated by common call stack. Each entry presents the number of allocations and the total bytes allocated for the given call stack. The list is sorted by the number of bytes allocated.
Suggested Reading:


Comments: Post a Comment

Links to this post:

Create a Link



<< Home


2004-2017 

This page is powered by Blogger. Isn't yours?