|
From: Nir T. <nir...@gm...> - 2009-11-29 08:20:25
|
Hello. I have been using valgrind for a very long time, and found it one of the best (if not The Best) debugging and bug finding tools ever. I have even ported applications from other archs to linux just to be able to run them through valgrind and track an elusive bug. However, there is one point where valgrind does not scratch my itch: reporting memory allocations. I have searched through the documentation, and did not find any way to report all the locations where memory is allocated. This is a main concern for many applications (think realtime) and is very hard to track in C++ code. I have been using a homebrew tool, based on LD_PRELOAD, to do just that, and then it struck me: why not add a valgrind tool? At the link below is a very crude implementation of a tool (which I named alloc) which does exactly this: http://www.cs.bgu.ac.il/~tzachar/code/alloc.tar.bz2 alloc reports memory allocations using the error reporting mechanisms of valgrind, and supports suppressions of specific errors using the core suppressions services. alloc also supports reporting errors starting after a predetermined number of allocations have occurred (for example, after all of the memory pools used by the program have been filled). I would really like to see this tool, or some kind of an equivalent tool (probably added to memcheck?), added to the default valgrind branch. I would also like to hear your opinions, comments and suggestions. Cheers, Nir. |
|
From: John R. <jr...@bi...> - 2009-11-29 19:07:15
|
> ... any way to report all the locations
> where memory is allocated. ...
A static list of all the locations that _can_ allocate memory
is useful, especially for an embedded environment ("If any location
_can_ allocate memory, then eventually it _will_, often when memory
is least available.")
A pipeline such as this will identify all the compilation units
with calls to alloc or new:
nm -gop $(find . -name '*.[oa]') | grep -E 'alloc|new'
A pipeline such as this will identify the locations of calls
to alloc or new:
readelf --relocs $(find . -name '*.o') | grep -E 'alloc|new'
You may wish to insert " | c++filt " into the pipeline
to demangle subroutine names. Also 'addr2line' can help
identify line numbers.
--
|
|
From: Nir T. <nir...@gm...> - 2009-11-30 05:33:30
|
On Sun, Nov 29, 2009 at 9:06 PM, John Reiser <jr...@bi...> wrote:
>> ... any way to report all the locations
>> where memory is allocated. ...
>
> A static list of all the locations that _can_ allocate memory
> is useful, especially for an embedded environment ("If any location
> _can_ allocate memory, then eventually it _will_, often when memory
> is least available.")
>
> A pipeline such as this will identify all the compilation units
> with calls to alloc or new:
> nm -gop $(find . -name '*.[oa]') | grep -E 'alloc|new'
>
> A pipeline such as this will identify the locations of calls
> to alloc or new:
> readelf --relocs $(find . -name '*.o') | grep -E 'alloc|new'
>
> You may wish to insert " | c++filt " into the pipeline
> to demangle subroutine names. Also 'addr2line' can help
> identify line numbers.
This is a great suggestion, and will work spectacularly for plain C
code. However, for C++ code, you will generally need the entire call
graph to understand where the allocation comes from. Consider the
following simple example:
#include <iostream>
#include <vector>
std::vector<int> goo()
{
std::vector<int> vec;
vec.push_back(1);
return vec;
}
int main()
{
std::vector<int> vec = goo();
std::cout << vec.front() << std::endl;
return 0;
}
and then:
> nm -gop test | grep -E 'alloc|new' | c++filt
test:000000000040107c W
__gnu_cxx::new_allocator<int>::deallocate(int*, unsigned long)
test:0000000000400da8 W __gnu_cxx::new_allocator<int>::~new_allocator()
test:000000000040109c W std::_Vector_base<int, std::allocator<int>
>::_M_deallocate(int*, unsigned long)
test:0000000000400e48 W std::_Vector_base<int, std::allocator<int>
>::_M_get_Tp_allocator()
test:0000000000400de2 W
__gnu_cxx::new_allocator<int>::new_allocator(__gnu_cxx::new_allocator<int>
const&)
test: U std::__throw_bad_alloc()@@GLIBCXX_3.4
test:0000000000400ebc W std::_Vector_base<int, std::allocator<int>
>::_M_get_Tp_allocator() const
test:0000000000400e56 W __gnu_cxx::new_allocator<int>::construct(int*,
int const&)
test:0000000000401406 W std::_Vector_base<int, std::allocator<int>
>::_M_allocate(unsigned long)
test:0000000000401048 W __gnu_cxx::new_allocator<int>::max_size() const
test:00000000004013bc W
__gnu_cxx::new_allocator<int>::allocate(unsigned long, void const*)
test:0000000000400d86 W __gnu_cxx::new_allocator<int>::new_allocator()
not much info there, except that some allocations are related to
vectors. And believe me, when you start using some of the frameworks
in boost, you will be at a total loss, especially if the code you are
inspecting is not your own...
Your point of view can also be applied as to why do we need callgrind,
when we can perform a static analysis of our code, which will give us
the same results? Because it is much harder to do so (and even
impossible in some cases).
Cheers,
Nir.
|
|
From: Josef W. <Jos...@gm...> - 2009-11-30 12:50:45
|
Am Sonntag 29 November 2009 09:20:14 schrieb Nir Tzachar: > Hello. > > I have been using valgrind for a very long time, and found it one of > the best (if not The Best) debugging and bug finding tools ever. I > have even ported applications from other archs to linux just to be > able to run them through valgrind and track an elusive bug. > > However, there is one point where valgrind does not scratch my itch: > reporting memory allocations. I have searched through the > documentation, and did not find any way to report all the locations > where memory is allocated. Sorry for my blatant ignorance for your use case. What are the features missing from, e.g. massif, to fit your needs? Josef |
|
From: Nir T. <nir...@gm...> - 2009-11-30 12:55:37
|
On Mon, Nov 30, 2009 at 2:49 PM, Josef Weidendorfer <Jos...@gm...> wrote: > Am Sonntag 29 November 2009 09:20:14 schrieb Nir Tzachar: >> Hello. >> >> I have been using valgrind for a very long time, and found it one of >> the best (if not The Best) debugging and bug finding tools ever. I >> have even ported applications from other archs to linux just to be >> able to run them through valgrind and track an elusive bug. >> >> However, there is one point where valgrind does not scratch my itch: >> reporting memory allocations. I have searched through the >> documentation, and did not find any way to report all the locations >> where memory is allocated. > > Sorry for my blatant ignorance for your use case. > What are the features missing from, e.g. massif, to fit your needs? Well, I do not care about the _total_ memory consumption, just the allocations themselves. Usually, I use memory pools, and just allocate from them. I do not care if they are large (I do, but this is another issue), but that _all_ code paths really use the pools and do not hide any unknown allocation behind the scenes. If massif can just report where ALL allocations are taking place and be able to suppress some of them, I would be a happy camper ;) |