From: Theodoros V. K. <th...@gm...> - 2009-05-07 06:09:05
|
Hi, I apologise beforehand if this has been discussed before, but in the list archives I only found a 2005 2-message thread that went nowhere. I do not have any experience with the Valgrind code, so if I sound ignorant it's probably because I am :-) I just spent two days trying to find a memory leak, even with valgrind. The program (not my code, thank goodness) was so convoluted that it was nearly impossible to keep track of the allocated block pointers, since they would be suffled back and forth between some stack-like structures as the thing worked. I thought it would very helpful if Valgrind could provide one or both of the following: - The last place in the program where a pointer to a particular block was used. I think this would be useful for people wishing to fine-tune their memory usage in general. It would also show a candidate location for that missing free()... - The last place where a pointer to a block was clobbered/lost, which is a probable location for the actual leak As for the implementation (warning: rampant ignorance ahead), it seems to me that something similar to the valid-value tracking mechanism could be used: - have a bitmap (P-bits ?) that marks certain addresses as pointers. - when a block is allocated, mark the location of the returned pointer in the bitmap. - when a pointer is copied, adjust the bitmap to include the new address. - when a pointer is used mark the place in the block metadata. This might be more accurate if any access to a block was tracked in general. - when the stack is adjusted/blocks freed/etc check all marked locations and update the metadata for any blocks that lost a pointer. If we had a pointer counter it might even be possible to detect memory leaks on the fly. - same for any clobbered pointers. No idea how to deal with the common ptr++ case. Maybe show this info only for definitely lost blocks ? Then corroborate the info collected above with the definite/potential loss info to increase accuracy (maybe for both ?). I understand that this could be quite slow, but I think it would be worth it. Even a slowdown similar to the one induced by --track-origins=yes would be acceptable IMO. And it could always be optional... Does this sound stupid or doable ? Regards, Theodoros Kalamatianos |
From: John R. <jr...@Bi...> - 2009-05-07 15:09:09
|
> - The last place where a pointer to a block was clobbered/lost, which is a > probable location for the actual leak Search the Web for "valgrind omega". -- |
From: Theodoros V. K. <th...@gm...> - 2009-05-08 04:56:35
|
On Thu, 7 May 2009, John Reiser wrote: >> - The last place where a pointer to a block was clobbered/lost, which >> is a probable location for the actual leak > > Search the Web for "valgrind omega". Ouch, it's even in the valgrind distribution, although disabled by default and undocumented in the wiki. And Google is almost impossible to get to come up with it. The implementation is similar to my thoughts, but in a working stage. I guess I had already suspected what I proposed was not all that new :-) Yes, this does seem to be exactly what I had in mind, although it does not seem to provide the "last-used-at" location, which might also be very useful. I'll see if I can try it out. The main issue is that omega seems to be collecting quite a bit of dust now. Pity... Regards, Theodoros Kalamatianos |
From: Nicholas N. <n.n...@gm...> - 2009-05-07 22:49:40
|
On Fri, May 8, 2009 at 12:49 AM, John Reiser <jr...@bi...> wrote: >> - The last place where a pointer to a block was clobbered/lost, which is a >> probable location for the actual leak > > Search the Web for "valgrind omega". This paper is related too: author = {Jonas Maebe and Michiel Ronsse and Koen De Bosschere}, title = {Precise detection of memory leaks}, booktitle = {Proceedings of the Second International Workshop on Dynamic Analysis (WODA 2004)}, pages = {}, address = {Edinburgh, Scotland}, month = may, year = 2004, In general, what you are proposing is possible, but it's not easy, is really slow and would be lots of extra code in Memcheck. Nick |
From: Theodoros V. K. <th...@gm...> - 2009-05-08 05:06:37
|
On Fri, 8 May 2009, Nicholas Nethercote wrote: > This paper is related too: > > author = {Jonas Maebe and Michiel Ronsse and Koen De Bosschere}, > title = {Precise detection of memory leaks}, > booktitle = {Proceedings of the Second International Workshop on Dynamic > Analysis (WODA 2004)}, > pages = {}, > address = {Edinburgh, Scotland}, > month = may, > year = 2004, I'll have a look at it. > In general, what you are proposing is possible, but it's not easy, is > really slow and would be lots of extra code in Memcheck. What if it was done in two passes? Run memcheck normally, and then re-run valgrind repeatedly in order to track a specific memory leak each time. You could say e.g. --tool=analyse-leak --with-alloc=foo.c:111 and have valgrind track those pointers only. Could we exploit that to make things easier speed-wise and coding-wise? IMO when you _know_ you have a problem, a slower but effective valgrind is definitely acceptable. Cheers, Theodoros |
From: Nicholas N. <n.n...@gm...> - 2009-05-08 06:10:13
|
On Fri, May 8, 2009 at 3:06 PM, Theodoros V. Kalamatianos <th...@gm...> wrote: >> >> In general, what you are proposing is possible, but it's not easy, is >> really slow and would be lots of extra code in Memcheck. > > What if it was done in two passes? Run memcheck normally, and then re-run > valgrind repeatedly in order to track a specific memory leak each time. You > could say e.g. --tool=analyse-leak --with-alloc=foo.c:111 and have valgrind > track those pointers only. Could we exploit that to make things easier > speed-wise and coding-wise? Two passes introduces problems of its own -- it's great if you have a totally deterministic program, otherwise you're in trouble. Or you can use deterministic replay techniques but that's more complication. > IMO when you _know_ you have a problem, a slower but effective valgrind is > definitely acceptable. Of course. My broader point is that there's an enormous difference between proposing something and implementing it, especially when the proposal is ambitious. Nick |
From: Julian S. <js...@ac...> - 2009-05-08 07:08:38
|
On Friday 08 May 2009, Theodoros V. Kalamatianos wrote: > On Fri, 8 May 2009, Nicholas Nethercote wrote: > > This paper is related too: > > > > author = {Jonas Maebe and Michiel Ronsse and Koen De Bosschere}, > > title = {Precise detection of memory leaks}, > > booktitle = {Proceedings of the Second International Workshop on > > Dynamic Analysis (WODA 2004)}, > > pages = {}, > > address = {Edinburgh, Scotland}, > > month = may, > > year = 2004, > > I'll have a look at it. > > > In general, what you are proposing is possible, but it's not easy, is > > really slow and would be lots of extra code in Memcheck. I'm not convinced it's really possible. The basic problem is that, due to how the compiler generates code, the last pointer to a block can be overwritten at some place which is arbitrarily far away (but in the same procedure) from where it is overwritten in the source, thus leading to a nonsensical error report. How can this happen? Imagine a procedure P which is quite large, and a block B. Relatively early in P, there is high register pressure and so a copy of the pointer to B written to a spill slot. A bit further along, the last pointer to B is overwritten in the source level, but the tool makes no comment because there's a copy in the spill slot. Then further along in P, a different value is written into the spill slot. At this point, the tool complains, but the source location is completely wrong. What's more, because it's a spill store, there may not even be any source level store for the user to see, at the stated source line. I would be interested to hear if the authors of the abovementioned paper managed to solve this problem. If you can devise a scheme that works reliably in the presence of spilling (viz, stack loads/stores introduced invisibly by the compiler) then you might be heading in a good direction. J |
From: Theodoros V. K. <th...@gm...> - 2009-05-08 20:54:36
|
On Fri, 8 May 2009, Julian Seward wrote: > I'm not convinced it's really possible. The basic problem is that, due > to how the compiler generates code, the last pointer to a block can be > overwritten at some place which is arbitrarily far away (but in the same > procedure) from where it is overwritten in the source, thus leading to a > nonsensical error report. Hmm, after my little leak-hunting expedition this week, I'd settle even for a tool that shows where any pointer (not just the last) to a block is overwritten. Or maybe the last N pointers that were lost. It would be better than nothing... I actually tried valgrind-3.3.0 and omega. The produced information was not really useful, partly because of the structure of the tested program and partly because of the fact that any accidentally left-over pointer will cover up the leak. I won't even go to the impediments the compiler introduces. I am now thinking that knowing where a particular block was last used might be a tad more useful than the location of the actual leak. > If you can devise a scheme that works reliably in the presence of spilling > (viz, stack loads/stores introduced invisibly by the compiler) then you might > be heading in a good direction. That was one of my main problems with gcc. For example, even with -O0 static functions would still disappear, as if they were macros. Several variables would only be registers or promptly disappear as well. It was surpsingly difficult to figure out in some cases. Perhaps we should attempt to convince the GCC people to have an --I-mean-it-really-do-not-optimize flag. Cheers, Theodoros |