|
From: Gili G. <gi...@br...> - 2013-03-14 10:50:35
|
Hello John.
I already went over the manual, and did not find anything that helped including the --freelist-* flags.
I found answers for all of your questions below, but they are not relevant any more.
Following your advice to construct the smallest stand-alone test case,
I saw that the problem persists if tested at the start of main() when using the same build system.
After a lot of further testing I found the reason:
The executable that valgrind examines is statically linked.
It looks like valgrind must work with a shared glibc to recognize calls to malloc/free.
BTW The identification of uninitialized memory also does not work properly
with the statically linked executable.
I do not see this information in the manual, perhaps it is worth adding to the "Getting Started" section.
In case you still want a full test case, here it is, to be compiled with: gcc -m32 -g -static test.c
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
unsigned int *p;
printf("======================================================= malloc\n");
if ((p = malloc(24))) {
int i;
for (i=0; i<=5; ++i) {
p[i]=i;
}
p[0]=p[6]+p[7]+p[8];
p[1]=p[-1]+p[-2]+p[-3];
printf("======================================================= free\n");
free(p);
p[1] = p[0];
}
return 0;
}
Thanks for the help,
Gili
> > I am trying to find memory corruption using valgrind/memcheck.
> > I am running a big executable, and noticed that memory access outside allocated areas is not detected. This happens after very many memory allocations are performed.
> How big (numbers, please)? Run /usr/bin/top and report the VIRT RES SHR amounts
> for the process, both without and with valgrind/memcheck.
> How many allocations and how many calls to free()?
> What is the distribution of block sizes?
> What is the distribution of calls to malloc, realloc, memalign, mmap?
> > I am testing access to illegal memory and finding that access to memory beyond the boundaries of memory just allocated by malloc is not reported.
> > Access to memory after it is freed by free() is not reported.
> > Access to memory which is not mapped in virtual memory is reported.
> >
> > This is not due to too many errors, and I suspect that the valgrind data structures holding allocations and de-allocations get full, and therefore stop functioning. This is just a guess, I have no information about the mechanism. I do know that the executable uses a big amount of memory allocations.
> There is no limit to the tracking of blocks which have been allocated
> but not yet free()d. There are some limits on tracking accesses to blocks
> which have been free()d. The address space is tracked as free, but the
> identity of the most recent block that was associated with that space
> is forgotten. First, large blocks (--freelist-big-blocks=<number>)
> lose their identity immediately upon free(). Second, there is a queue
> (--freelist-vol=<number>) of free()d small blocks, and old blocks
> are forgotten as new ones are free()d.
> >
> > Is there a way to check print the memory allocations and de-allocations that valgrind is tracking at a specific point?
> Read The Fine Manual. If you don't know where it is,
> then search for "valgrind manual".
> > Is there a limit to the number of allocations that can be handled?
> There is no limit other than total address space available to the process.
> >
> > I am running on Linux x86_64.
> > I tried using both valgrind-3.8.1 and valgrind-3.5.0 that comes with the open Suse 11.3 I am running on.
> > I tried this with both a 32 bit and a 64 bit executable.
> > Example command line that I use: valgrind --trace-children=yes --error-limit=no -v ./executable
> Thank you for those details! You care enough that there is hope for this case.
> >
> > Does anyone have an idea what to do here?
> Construct the smallest stand-alone test case which illustrates the problem(s),
> and post that code. If you actually do wade into this then you will find that
> valgrind/memcheck really does work even for "big programs", and that there is
> something unusual about your program or environment that triggers the problems.
|
|
From: John R. <jr...@bi...> - 2013-03-14 20:46:35
|
> I already went over the manual, and did not find anything that helped including the --freelist-* flags. Please read more carefully. I found relevant material which I pinpoint below in the hope that specific references may help increase understanding for future uses. I downloaded the manual from http://www.valgrind.org/docs/download_docs.html pointing to http://www.valgrind.org/docs/manual/valgrind_manual.pdf (1301228 bytes) titled Valgrind Documentation, Release 3.8.0 10 August 2012 . Then I read: In the chapter Memcheck: a memory error detector, section 4.3. Memcheck Command-Line Options, printed p.58, pdf p.70 of 319: --freelist-vol=<number> [default: 20000000] and on printed p.59, pdf p.71 of 319: --freelist-big-blocks=<number> [default: 1000000] Hints to these command line options also appear in the output from "valgrind --help". > I found answers for all of your questions below, but they are not relevant any more. Well, actually some of them still provide important educational clues. Using the standalone test case that you posted, and comparing static linking versus dynamic on x86_64: VIRT RES SHR /usr/bin/top 1012 16 8 ./my_test static linking libc.a 4112 312 240 ./my_test dynamic linking libc.so.6 If the SHR column shows only 8KiB, then that is a very strong clue that the program is not using a shared libc. As you discovered, this turns out to be the reason for the problems that you encountered. > > Following your advice to construct the smallest stand-alone test case, > I saw that the problem persists if tested at the start of main() when using the same build system. > After a lot of further testing I found the reason: > The executable that valgrind examines is statically linked. > It looks like valgrind must work with a shared glibc to recognize calls to malloc/free. > BTW The identification of uninitialized memory also does not work properly > with the statically linked executable. > > I do not see this information in the manual, perhaps it is worth adding to the "Getting Started" section. In the Valgrind Frequently Asked Questions, section 4. Valgrind behaves unexpectedly, 4.5. Memcheck doesn’t report any errors and I know my program has errors, printed p.6, pdf p.183 of 319: Second, if your program is statically linked, most Valgrind tools won’t work as well, because they won’t be able to replace certain functions, such as malloc, with their own versions. In the NEWS section, Release 3.8.0 (10 August 2012), TOOL CHANGES, * Non-libc malloc implementations are now supported. This is useful for tools that replace malloc (Memcheck, Massif, DRD, Helgrind). Using the new option --soname-synonyms, such tools can be informed that the malloc implementation is either linked statically into the executable, or is present in some other shared library different from libc.so. This makes it possible to process statically linked programs, and programs using other malloc libraries, for example TCMalloc or JEMalloc. So valgrind-3.8.0 says that it can handle static linking of malloc, but the user must help. > > In case you still want a full test case, here it is, to be compiled with: gcc -m32 -g -static test.c Thank you for posting the code; I snipped it from this reply. "Construct the smallest bad example" is an amazingly helpful approach. I'm glad that you succeeded in finding the problem. -- |
|
From: Philippe W. <phi...@sk...> - 2013-03-14 21:08:06
|
On Thu, 2013-03-14 at 13:47 -0700, John Reiser wrote: > In the NEWS section, Release 3.8.0 (10 August 2012), TOOL CHANGES, > * Non-libc malloc implementations are now supported. This is useful > for tools that replace malloc (Memcheck, Massif, DRD, Helgrind). > Using the new option --soname-synonyms, such tools can be informed > that the malloc implementation is either linked statically into the > executable, or is present in some other shared library different > from libc.so. This makes it possible to process statically linked > programs, and programs using other malloc libraries, for example > TCMalloc or JEMalloc. > > So valgrind-3.8.0 says that it can handle static linking of malloc, > but the user must help. A little addition: the user must help if malloc is statically linked. However, at least at this moment, the application cannot be *fully* statically linked. The reason is that the Valgrind code that triggers the replacement is itself a shared object, which is LD_PRELOAD-ed. I still have on my list of things to do in low priority to see if this last limitation can be bypassed. For example, if the tool detects that the replacement code was not PRELOADED-ed, then the tool might mmap the code rwx. This trick might help fully static executable to be better supported. At this stage, just a brainstorming idea that will probably explode in pieces once looked at more in depth. Philippe |