tags:

views:

1817

answers:

4

Hi all,

I have an application that interacts with external devices using serial communication. There are two versions of the device differing in their implementations. -->One is developed and tested by my team -->The other version by a different team. Since the other team has left, our team is looking after it's maintenance. The other day while testing the application I noticed that the application takes up 60 Mb memory at startup and to my horror it's memory usage starts increasing with 200Kb chunks, in 60 hrs it shoots up to 295 Mb though there is no slow down in the responsiveness and usage of application. I tested it again and again and the same memory usage pattern is repeated.

The application is made in C++,Qt 4.2.1 on RHEL4.

I used mtrace to check for any memory leaks and it shows no such leaks. I then used valgrind memcheck tool, but the messages it gives are cryptic and not very conclusive, it shows leaks in graphical elements of Qt, which on scrutiny can be straightaway rejected.

I am in a fix as to what other tools/methodologies can be adopted to pinpoint the source of these memory leaks if any. -->Also, in a larger context, how can we detect and debug presence of memory leaks in a C++ Qt application? -->How can we check, how much memory a process uses in Linux?

I had used gnome-system-monitor and top command to check for memory used by the application, but I have heard that results given by above mentioned tools are not absolute.

EDIT:

I used ccmalloc for detecting memory leaks and this is the error report I got after I closed the application. During application execution, there were no error messages.

|ccmalloc report|

=======================================================

| total # of| allocated | deallocated | garbage |

+-----------+-------------+-------------+-------------+

| bytes| 387325257 | 386229435 | 1095822 |

+-----------+-------------+-------------+-------------+

|allocations| 1232496 | 1201351 | 31145 |

+-----------------------------------------------------+

| number of checks: 1 |

| number of counts: 2434332 |

| retrieving function names for addresses ... done. |

| reading file info from gdb ... done. |

| sorting by number of not reclaimed bytes ... done. |

| number of call chains: 3 |

| number of ignored call chains: 0 |

| number of reported call chains: 3 |

| number of internal call chains: 3 |

| number of library call chains: 1 |

=======================================================

|

| 3.1% = 33.6 KB of garbage allocated in 47 allocations

| |

| | 0x???????? in

| |

| | 0x081ef2b6 in

| | at src/wrapper.c:489

| |

| | 0x081ef169 in <_realloc>

| | at src/wrapper.c:435

| |

| `-----> 0x081ef05c in

| at src/wrapper.c:318

|

| 0.8% = 8722 Bytes of garbage allocated in 35 allocations

| |

| | 0x???????? in

| |

| | 0x081ef134 in

| | at src/wrapper.c:422

| |

| `-----> 0x081ef05c in

| at src/wrapper.c:318

|

| 0.1% = 1144 Bytes of garbage allocated in 5 allocations

| |

| | 0x???????? in

| |

| | 0x081ef1cb in

| | at src/wrapper.c:455

| |

| `-----> 0x081ef05c in

| at src/wrapper.c:318

|

`------------------------------------------------------

free(0x09cb650c) after reporting

(This can happen with static destructors.

When linking put `ccmalloc.o' at the end (for gcc) or

in front of the list of object files.)

free(0x09cb68f4) after reporting

free(0x09cb68a4) after reporting

free(0x09cb6834) after reporting

free(0x09cb6814) after reporting

free(0x09cb67a4) after reporting

free(0x09cb6784) after reporting

free(0x09cb66cc) after reporting

free(0x09cb66ac) after reporting

free(0x09cb65e4) after reporting

free(0x09cb65c4) after reporting

free(0x09cb653c) after reporting

ccmalloc_report() called in non valid state

I have no clue, what this means, it doesn't seem to indicate any memory leaks to me? I may be wrong. Does anyone of you have come across such a scenario? link|edit|delete

+1  A: 

You said you tried Valgrind's memcheck tool; you should also try the massif tool, which should be able to graph the heap usage over time, and tell you where the memory was allocated from.

One of the reasons why top isn't too useful to measure memory usage is that they don't take into account that memory is often shared between processes. For the best overview on where the process has allocated memory, I recommend using a recent Linux kernel and checking /proc/<pid>/maps for your process. This shows what memory is mapped to that process and from where. For example, here's a snippet from konqueror on my system.

b732a000-b7a20000 r-xp 00000000 fd:05 205437     /usr/lib/qt3/lib/libqt-mt.so.3.3.8
Size:               7128 kB
Rss:                3456 kB
Pss:                 347 kB
Shared Clean:       3452 kB
Shared Dirty:          0 kB
Private Clean:         4 kB
Private Dirty:         0 kB
Referenced:         3452 kB

The important thing here is that, although the resident set resulting from the load of libqt-mt.so.3.3.8 is 3456kB, all but 4kB of that is shared between all processes which loaded the library, so it's a one-off system-wide cost. top doesn't expose this information, so just reading the RSS from top is misleading.

Intransigent Parsnip
+2  A: 

Valgrind can be a bitch if you don't really read the manuals or whatever documentation is actually available (man page for starters) - but they are worth it.

Basicly, you could start by running the valgrind on your application with --gen-suppressions=all and then create a suppressions for each block that is originating from QT itself and then use the suppression file to block those errors and you should be left with only with errors in your own code.

Also, you could try to use valgrind thru a alleyoop frontend if that makes things easier for you.

There are also bunch of other tools that can be used to detect memory leaks and Linux Journal has article about those here: http://www.linuxjournal.com/article/6556

And last, in some cases, some static analysis tools can spot memory errors too..

rasjani
+1  A: 

I'd like to make the minor point that just because the meory used by a process is increasing, it does not follow that you have a memory leak. Take a word processor as an example - as you write text, the memory usage increases, but there is no leak. Most processes in fact increase their memoryy usage as they run, often until they reach some sort of near steady-state, where objects been created are balanced by old objects being destroyed.

anon
Point noted Mr Neil but inn my case it starts at 60 MB and in 60 hrs reached 295 MB. This I guess is a memory leak but on reviewing the code I couldn't find any leaks as such.
rocknroll
A: 

I used ccmalloc for detecting memory leaks and this is the error report I got after I closed the application. During application execution, there were no error messages.

|ccmalloc report|

=======================================================

| total # of| allocated | deallocated | garbage |

+-----------+-------------+-------------+-------------+

| bytes| 387325257 | 386229435 | 1095822 |

+-----------+-------------+-------------+-------------+

|allocations| 1232496 | 1201351 | 31145 |

+-----------------------------------------------------+

| number of checks: 1 |

| number of counts: 2434332 |

| retrieving function names for addresses ... done. |

| reading file info from gdb ... done. |

| sorting by number of not reclaimed bytes ... done. |

| number of call chains: 3 |

| number of ignored call chains: 0 |

| number of reported call chains: 3 |

| number of internal call chains: 3 |

| number of library call chains: 1 |

=======================================================

|

| 3.1% = 33.6 KB of garbage allocated in 47 allocations

| |

| | 0x???????? in

| |

| | 0x081ef2b6 in

| | at src/wrapper.c:489

| |

| | 0x081ef169 in <_realloc>

| | at src/wrapper.c:435

| |

| `-----> 0x081ef05c in

| at src/wrapper.c:318

|

| 0.8% = 8722 Bytes of garbage allocated in 35 allocations

| |

| | 0x???????? in

| |

| | 0x081ef134 in

| | at src/wrapper.c:422

| |

| `-----> 0x081ef05c in

| at src/wrapper.c:318

|

| 0.1% = 1144 Bytes of garbage allocated in 5 allocations

| |

| | 0x???????? in

| |

| | 0x081ef1cb in

| | at src/wrapper.c:455

| |

| `-----> 0x081ef05c in

| at src/wrapper.c:318

|

`------------------------------------------------------

free(0x09cb650c) after reporting

(This can happen with static destructors.

When linking put `ccmalloc.o' at the end (for gcc) or

in front of the list of object files.)

free(0x09cb68f4) after reporting

free(0x09cb68a4) after reporting

free(0x09cb6834) after reporting

free(0x09cb6814) after reporting

free(0x09cb67a4) after reporting

free(0x09cb6784) after reporting

free(0x09cb66cc) after reporting

free(0x09cb66ac) after reporting

free(0x09cb65e4) after reporting

free(0x09cb65c4) after reporting

free(0x09cb653c) after reporting

ccmalloc_report() called in non valid state

I have no clue, what this means, it doesn't seem to indicate any memory leaks to me? I may be wrong. Does anyone of you have come across such a scenario?

rocknroll