the application is an algorithm running in a loop, reading through
drivers some pin inputs, doing some processing and sending the results
to another application (GUI), doing some logging, and driving (through
drivers again) some pin outputs.
using the command 'top' i see that the %memory used by this
application is slowly but steadily increasing...
i know that there is a suite of debugging memory problems called
Valgrind, but unfortunately they do not offer ARM (32bit) support
yet..
is there another program i could consider that could tell me about
memory leaks? any other pointers that might help me?
thank you for your advice.
nass
> using the command 'top' i see that the %memory used by this
> application is slowly but steadily increasing...
This in itself does not always imply that there is a leak.
You could have an ever-expanding data structure, or heap
fragmentation.
> i know that there is a suite of debugging memory problems called
> Valgrind, but unfortunately they do not offer ARM (32bit) support
> yet..
There is a *ton* of malloc-debug libraries. You don't need VG just
to find memory leaks. Just google for "debug malloc", and link one
into your program.
Your other approach is to compile the code for Linux/x86, and link in
a "simulator" for parts that read the hardware. Then you can use any
of the tools available for Linux/x86 -- VG, Purify, Insure++, etc.
Cheers,
--
In order to understand recursion you must first understand recursion.
Remove /-nsp/ for email.
yes an ever expanding data structure, i know i do not have. still is
there a way to check that too? smth like i'll attach a gdb server to
the target machine, and check variable sizes at the time of the
pause.... is it possible? but what is heap fragmentation?
>
> > i know that there is a suite of debugging memory problems called
> > Valgrind, but unfortunately they do not offer ARM (32bit) support
> > yet..
>
> There is a *ton* of malloc-debug libraries. You don't need VG just
> to find memory leaks. Just google for "debug malloc", and link one
> into your program.
>
> Your other approach is to compile the code for Linux/x86, and link in
> a "simulator" for parts that read the hardware. Then you can use any
> of the tools available for Linux/x86 -- VG, Purify, Insure++, etc.
>
> Cheers,
> --
> In order to understand recursion you must first understand recursion.
> Remove /-nsp/ for email.
Thank you
yes there is something i haven't noted and it might be important...
i only use a few 'new' operators in the constructors (and
corresponding 'delete' operators in the destructors) so there is no
forseeable expanding allocation of memory from the heap during
runtime..... or is there? this sounds stupid and desperarte but
really: is it possible that if i replace all the new in the
constructors with normal variables... i can get passed the memory
leakage problems?
> yes there is something i haven't noted and it might be important...
> i only use a few 'new' operators in the constructors (and
> corresponding 'delete' operators in the destructors) so there is no
> forseeable expanding allocation of memory from the heap during
> runtime..... or is there?
Actually, there is.
Perhaps you've neglected to follow the advice from
Effective-C++ Item 11, aka the 'Rule of three' ?
See http://www.ddj.com/cpp/184401400
Also, 'new' is far from being the only way you can leak memory --
there are many other ways to do that. For example:
while (p = receive_packet()) {
char *p = strdup(p->name); ...
// Oops -- forgot to free(p);
}
or
while (p = receive_packet()) {
pthread_t tid;
pthread_create(&tid, 0, func, p);
// Oops -- forgot to join the thread
}
etc. etc.
hm, ok the 'rule of three' seems fair enough but it seems to me it is
important when you copy and destroy objects at runtime...
i do not destroy any object at run time, i instantiate some objects in
the initialization stages and keep the running for ever. do the rule
of three still apply???
> Also, 'new' is far from being the only way you can leak memory --
> there are many other ways to do that. For example:
>
> while (p = receive_packet()) {
> char *p = strdup(p->name); ...
> // Oops -- forgot to free(p);
> }
>
also in such cases, p is not free'd by 'me' but it does get freed on
exit from functions... does it not?
strdup returns a dynamically allocated copy of its argument, which must
be freed by the caller.
--
Az.
www: http://www.azazel.net/
pgp: http://www.azazel.net/~azazel/az_key.asc
>> Perhaps you've neglected to follow the advice from
>> Effective-C++ Item 11, aka the 'Rule of three' ?
>
> hm, ok the 'rule of three' seems fair enough but it seems to me it is
> important when you copy and destroy objects at runtime...
> i do not destroy any object at run time, i instantiate some objects in
> the initialization stages and keep the running for ever. do the rule
> of three still apply???
Probably. You may not be copying objects intentionally, but compiler
may be doing that for you without you realizing that.
Declare a private copy constructor and operator=(), but don't
implement them. If your code still compiles and links, then objects
were not copied/assigned. If it doesn't, then they were.
>> while (p = receive_packet()) {
>> char *p = strdup(p->name); ...
>> // Oops -- forgot to free(p);
>> }
>>
>
> also in such cases, p is not free'd by 'me' but it does get freed on
> exit from functions... does it not?
Not at all.
The mere fact that you think it might somehow get free()d,
shows utter lack of understanding of dynamic memory management.
You should probably seek immediate help of a local 'C' wizard.
im not referring to strdup exclusively. in fact im not using threads
and i dunno how to program them.
but do seriously local variables NOT get free'd on exit from function
calls??? so pointers declared locally do not get free'd?
i mean this is really important... is it not like that?
nass
[...]
>> >> while (p = receive_packet()) {
>> >> char *p = strdup(p->name); ...
>> >> // Oops -- forgot to free(p);
>> >> }
>>
>> > also in such cases, p is not free'd by 'me' but it does get freed on
>> > exit from functions... does it not?
>>
>> Not at all.
>>
>> The mere fact that you think it might somehow get free()d,
>> shows utter lack of understanding of dynamic memory management.
>> You should probably seek immediate help of a local 'C' wizard.
[...]
> im not referring to strdup exclusively. in fact im not using threads
> and i dunno how to program them.
> but do seriously local variables NOT get free'd on exit from function
> calls??? so pointers declared locally do not get free'd?
'The pointer' and 'what the pointer points to' are two different
things. The storage (if any) used to hold the pointer value is freed
on exist of the definining function. But this does not extend to
whatever object may have been located at that particular address.
>> In order to understand recursion you must first understand recursion.
>> Remove /-nsp/ for email.
[Please trim your replies just to the part you are replying to.]
> im not referring to strdup exclusively. in fact im not using threads
> and i dunno how to program them.
I didn't imply that you do. Merely that there are many different
ways to leak memory, besides calling new.
> but do seriously local variables NOT get free'd on exit from function
> calls??? so pointers declared locally do not get free'd?
> i mean this is really important...
Yes, this really *is* important.
As Rainer Weikusat explained, there are two separate "things"
here -- the pointer itself, and the "thing" that it points to.
The pointer itself resides on the stack, occupies 4 bytes (on a
32-bit machine), and these 4 bytes are "released back to the system"
(popped off stack) when the function returns.
The "thing" that the pointer points to may reside on stack, in the
"global data" section, or in heap (strdup returns memory from heap).
It may occupy 0, 20, 4000, or even 2147483647 bytes, and it does
*not* get automatically "released back to the system" just because
the function returns.
[BTW, this is "C memory management 101" -- stuff that every competent
C (and C++) programmer should understand completely.]
yeah yeah, thats true... i am an engineer.. not a programmer and im
struggling with c++ indeed.. learning really
i guess its time to some book.
thank you all for your help
keep in mind that i am not using malloc/new at all during runtime...
only on the constructors. so i can not replace some malloc calls with
the leak libraries and expect to see results.. it's got to be
something like vagrind, that just runs the executable as an argument
to valgrind executable...
also i tried simulating the driver inputs by some constant values on
a x86 machine, but when i try to run the application with valgrind it
halts execution after a while...for no apparent reason...the
documentation does not help either..
ill replicate the output and get back and post it..
> well, i have looked around my code quite a bit im freeing any
> pointers /pointers to structures that i declare in local functions and
Huh? Free()ing things you didn't *allocate* is much worse than
not free()ing things you did -- the former will likely crash,
the latter will merely leak.
> so i turned to finding some leak detector... however i have not
> google'd any that supports ARM...
You don't need anything that specifically supports ARM.
Just use dmalloc, or mpatrol.
> keep in mind that i am not using malloc/new at all during runtime...
If you are not using them (directly or indirectly), then you do
not need a leak detector -- no leak is possible without someone
calling malloc/realloc/calloc/memalign.
> also i tried simulating the driver inputs by some constant values on
> a x86 machine, but when i try to run the application with valgrind it
> halts execution after a while...
Does the 'simulator' also halt without Valgrind?
If so, you've found a bug in it.
If not, and you aren't running out of memory, then you've found a
bug in VG (but that's unlikely).
Also, you do not need to run simulator under VG for very long;
if you are leaking, VG will find it after just a couple of
iterations.
valgrind --gen-suppressions=yes --leak-check=yes controller
==21050== Memcheck, a memory error detector.
==21050== Copyright (C) 2002-2007, and GNU GPL'd, by Julian Seward et
al.
==21050== Using LibVEX rev 1732, a library for dynamic binary
translation.
==21050== Copyright (C) 2004-2007, and GNU GPL'd, by OpenWorks LLP.
==21050== Using valgrind-3.2.3, a dynamic binary instrumentation
framework.
==21050== Copyright (C) 2000-2007, and GNU GPL'd, by Julian Seward et
al.
==21050== For more details, rerun with: -v
==21050==
--21050-- DWARF2 CFI reader: unhandled CFI instruction 0:50
--21050-- DWARF2 CFI reader: unhandled CFI instruction 0:50
--21050-- DWARF2 CFI reader: unhandled CFI instruction 0:50
--21050-- DWARF2 CFI reader: unhandled CFI instruction 0:50
/*## once the program is running nothing appears on the console
window... this is the 'normal' running state... then i press ctrl+C..
and here is what follows..
btw ctrl+C is by no means a proper killing of the application.. there
is no handler for it... anyway here are the exit valgrind
messages...##*/
==21050==
==21050== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 21 from
1)
==21050== malloc/free: in use at exit: 91,425 bytes in 427 blocks.
==21050== malloc/free: 1,482 allocs, 1,055 frees, 254,588 bytes
allocated.
==21050== For counts of detected errors, rerun with: -v
==21050== searching for pointers to 427 not-freed blocks.
==21050== checked 191,448 bytes.
==21050==
==21050== 68 bytes in 1 blocks are possibly lost in loss record 39 of
50
==21050== at 0x401DB0E: calloc (vg_replace_malloc.c:279)
==21050== by 0x400EBDC: _dl_allocate_tls (in /lib/ld-2.3.6.so)
==21050== by 0x42757BE: pthread_create@@GLIBC_2.1 (in /lib/tls/
libpthread-2.3.6.so)
==21050== by 0x4040843: __aio_enqueue_request (in /lib/tls/
librt-2.3.6.so)
==21050== by 0x40413EF: aio_write (in /lib/tls/librt-2.3.6.so)
==21050== by 0x805B973: LogBase::AsynchWriteLine() (logger.cpp:531)
==21050== by 0x805B375: LogBase::logUpdate() (logger.cpp:442)
==21050== by 0x806A499: MainObj::Update() (core.cpp:631)
==21050== by 0x806CCB2: MainObj::Run() (core.cpp:1595)
==21050== by 0x806DBFD: main (main.cpp:81)
==21050==
==21050== ---- Print suppression ? --- [Return/N/n/Y/y/C/c] ---- y
{
<insert a suppression name here>
Memcheck:Leak
fun:calloc
fun:_dl_allocate_tls
fun:pthread_create@@GLIBC_2.1
fun:__aio_enqueue_request
fun:aio_write
fun:_ZN7LogBase15AsynchWriteLineEv
fun:_ZN7LogBase9logUpdateEv
fun:_ZN7MainObj6UpdateEv
fun:_ZN7MainObj3RunEv
fun:main
}
==21050==
==21050==
==21050== 6,986 bytes in 268 blocks are possibly lost in loss record
48 of 50
==21050== at 0x401CABB: operator new(unsigned) (vg_replace_malloc.c:
163)
==21050== by 0x40C7215: std::string::_Rep::_S_create(unsigned,
unsigned, std::allocator<char> const&) (in /usr/lib/libstdc++.so.
6.0.3)
==21050== by 0x40C79CB: std::string::_M_mutate(unsigned, unsigned,
unsigned) (in /usr/lib/libstdc++.so.6.0.3)
==21050== by 0x40C7CBD: std::string::assign(char const*, unsigned)
(in /usr/lib/libstdc++.so.6.0.3)
==21050== by 0x40C7E1B: std::string::operator=(char const*) (in /
usr/lib/libstdc++.so.6.0.3)
==21050== by 0x806DB4D: main (main.cpp:48)
==21050==
==21050== ---- Print suppression ? --- [Return/N/n/Y/y/C/c] ---- y
{
<insert a suppression name here>
Memcheck:Leak
fun:_Znwj
fun:_ZNSs4_Rep9_S_createEjjRKSaIcE
fun:_ZNSs9_M_mutateEjjj
fun:_ZNSs6assignEPKcj
fun:_ZNSsaSEPKc
fun:main
}
==21050==
==21050== LEAK SUMMARY:
==21050== definitely lost: 0 bytes in 0 blocks.
==21050== possibly lost: 7,054 bytes in 269 blocks.
==21050== still reachable: 84,371 bytes in 158 blocks.
==21050== suppressed: 0 bytes in 0 blocks.
==21050== Reachable blocks (those to which a pointer was found) are
not shown.
==21050== To see them, rerun with: --leak-check=full --show-
reachable=yes
that's pretty much it...
after 3 days of constant running the memory inflated again ..from 1.2
to 1.3 % of the memory.. still looking around.. for bugs
nass
> well i did manage to find the main source of inflation of the memory..
> some "new" was called during runtime on some object again and
> again ...
Mis-information #1 -- earlier you stated that you didn't call
malloc/new at runtime, only during initialization.
Now you've found that you were calling new at runtime after all.
This VG output:
> ==21050== malloc/free: 1,482 allocs, 1,055 frees, 254,588 bytes
"proves" that you continue to call malloc/free at runtime (unless
all 1055 calls to free() happened during initialization, which
is somewhat unlikely).
> ==21050== 68 bytes in 1 blocks are possibly lost in loss record 39 of 50
> ==21050== at 0x401DB0E: calloc (vg_replace_malloc.c:279)
> ==21050== by 0x400EBDC: _dl_allocate_tls (in /lib/ld-2.3.6.so)
> ==21050== by 0x42757BE: pthread_create@@GLIBC_2.1 (in /lib/tls/libpthread-2.3.6.so)
Mis-information #2 -- earlier you stated that you aren't using
threads, but in fact you *are* using them, although indirectly.
> ==21050== 6,986 bytes in 268 blocks are possibly lost in loss record 48 of 50
> ==21050== at 0x401CABB: operator new(unsigned) (vg_replace_malloc.c:163)
> ==21050== by 0x40C7215: std::string::_Rep::_S_create(...)
> ==21050== by 0x40C79CB: std::string::_M_mutate(...)
> ==21050== by 0x40C7CBD: std::string::assign(...)
> ==21050== by 0x40C7E1B: std::string::operator=(char const*)
> ==21050== by 0x806DB4D: main (main.cpp:48)
...
> after 3 days of constant running the memory inflated again ..from 1.2
> to 1.3 % of the memory.. still looking around.. for bugs
It is likely that the above 'possible leak' is in fact real; but
it's hard to tell what exactly is going on without knowing what
happens to the string assigned on line 48 of main.cpp