|
From: Szabolcs N. <ns...@po...> - 2011-06-30 14:30:33
|
in a custom allocator like
int *alloczero() {
int *p = malloc(sizeof *p);
if (*p)
*p = 0;
return p;
}
valgrind reports 'conditional jump..'
at line 'if (*p)', which is correct
and easy to suppress
but later whereever i read *p i get
'..uninitialised' value errors
eventhough it's clearly provably 0
now i'm wondering how to suppress these
warnings in a way that valgrind
understands that *p is 0
(the check is necessary because in
the code where it is used the page
is often zeroed out and we want to
aviod dirty pages)
|
|
From: John R. <jr...@bi...> - 2011-06-30 14:55:10
|
> int *alloczero() {
> int *p = malloc(sizeof *p);
>
> if (*p)
> *p = 0;
> return p;
> }
>
> valgrind reports 'conditional jump..'
> at line 'if (*p)', which is correct
> and easy to suppress
>
> but later whereever i read *p i get
> '..uninitialised' value errors
> eventhough it's clearly provably 0
>
> now i'm wondering how to suppress these
> warnings in a way that valgrind
> understands that *p is 0
Such [incorrect] warnings cannot be suppressed.
The memory state after the code:
if (*p)
*p = 0;
is an instance of control-dependent "re-convergent fanout",
and memcheck is not intelligent enough to recognize it.
Memcheck's "logical horizon" is too small to understand
the general concept.
Perhaps the best that you can do is modify the custom allocator
using something like:
-----
#include <valgrind.h>
if (RUNNING_ON_VALGRIND)
*p = 0;
else if (*p)
*p = 0;
-----
--
|
|
From: John R. <jr...@bi...> - 2011-06-30 15:58:43
|
On 06/30/2011 08:34 AM, Szabolcs Nagy wrote: > hm this is actually in the calloc implementation > of a libc (musl) > > i was testing with statically linked binaries > > now i see that with dynamic linking valgrind > knows calloc semantics (i guess it preloads > its own calloc) Yes. valgrind has an internal form of preloading which it calls 're-directing". Known allocators and various mem*() and str*() functions are re-directed to routines that are internal to valgrind. > is it possible to do the same for statically > linked binaries? (recognize calloc calls > and assume its output is always zeroed) I don't know how to do this except via enhancements inside valgrind. In the case of dynamic linking it is easier to recognize and to redirect calloc, malloc, strchr, memset, etc. -- |
|
From: WAROQUIERS P. <phi...@eu...> - 2011-06-30 19:06:23
|
>Perhaps the best that you can do is modify the custom allocator
>using something like:
>-----
> #include <valgrind.h>
>
> if (RUNNING_ON_VALGRIND)
> *p = 0;
> else if (*p)
> *p = 0;
I wonder if the above "if-s" are really needed.
I think that on many modern cpu (with pipe lines etc),
it might be faster to just do
*p = 0;
return p;
rather than to do one or more "if-s" to avoid an assignment.
I also believe that RUNNING_ON_VALGRIND has a certain cost even when
not running under valgrind.
So, in many case, the above code will incur the cost of two "if-s".
And so, always do:
*p = 0;
return p;
will always be faster (with or without valgrind),
and will not cause any strange errors with valgrind.
Would be worth verifying this (maybe with callgrind/cachegrind :).
Philippe
____
This message and any files transmitted with it are legally privileged and intended for the sole use of the individual(s) or entity to whom they are addressed. If you are not the intended recipient, please notify the sender by reply and delete the message and any attachments from your system. Any unauthorised use or disclosure of the content of this message is strictly prohibited and may be unlawful.
Nothing in this e-mail message amounts to a contractual or legal commitment on the part of EUROCONTROL, unless it is confirmed by appropriately signed hard copy.
Any views expressed in this message are those of the sender.
|
|
From: John R. <jr...@bi...> - 2011-06-30 20:28:15
|
On 06/30/2011 12:06 PM, WAROQUIERS Philippe wrote: >> Perhaps the best that you can do is modify the custom allocator >> using something like: >> ----- >> #include <valgrind.h> >> >> if (RUNNING_ON_VALGRIND) >> *p = 0; >> else if (*p) >> *p = 0; > > I wonder if the above "if-s" are really needed. > I think that on many modern cpu (with pipe lines etc), > it might be faster to just do > *p = 0; > return p; > > rather than to do one or more "if-s" to avoid an assignment. Omitting the 'if's certainly is faster locally. However, the question is globally: if the lower-level allocator (lower than this one) returns mmap(,,,MAP_ANONYMOUS,,) then the unconditional store of 0 causes an immediate dirtying of a page (all MAP_ANONYMOUS pages initially refer to the _same_ single, zeroed physical page) with the associated overhead for operating system trap. (The original poster mentioned this in another reply.) If the end user of the page never writes to it otherwise (which happens more often than one might expect naively) then the immediate store here will waste thousands of cycles. If "production" code really does require the fewest local cycles, then suitable conditional compilation can turn "if (RUNNING_ON_VALGRIND)" into "if (0)", and a good compiler will optimize. If total software life cycle cost matters more, as usually it does, then having a "live" test for valgrind that can be activated instantly, even in deployed code at customer installations, is exceedingly valuable. Being able to diagnose a bug discovered by a customer, and fix it in one day instead of several, is worth a lot of real money. -- |
|
From: WAROQUIERS P. <phi...@eu...> - 2011-06-30 20:36:01
|
>However, the question is globally: if the lower-level allocator (lower >than this one) returns mmap(,,,MAP_ANONYMOUS,,) then the unconditional >store of 0 causes an immediate dirtying of a page (all MAP_ANONYMOUS >pages initially refer to the _same_ single, zeroed physical page) >with the associated overhead for operating system trap. >(The original poster mentioned this in another reply.) >If the end user of the page never writes to it otherwise >(which happens more often than one might expect naively) >then the immediate store here will waste thousands of cycles. Effectively. Then an alternate solution is to call the client request VALGRIND_MAKE_MEM_DEFINED in the low level allocator, to mark the pages as defined. This will be a very little cost when not running under Valgrind and will also be more efficient under Valgrind than individually write each byte/integer or whatever. Philippe ____ This message and any files transmitted with it are legally privileged and intended for the sole use of the individual(s) or entity to whom they are addressed. If you are not the intended recipient, please notify the sender by reply and delete the message and any attachments from your system. Any unauthorised use or disclosure of the content of this message is strictly prohibited and may be unlawful. Nothing in this e-mail message amounts to a contractual or legal commitment on the part of EUROCONTROL, unless it is confirmed by appropriately signed hard copy. Any views expressed in this message are those of the sender. |
|
From: Julian S. <js...@ac...> - 2011-07-01 07:00:42
|
On Thursday, June 30, 2011, Szabolcs Nagy wrote:
> in a custom allocator like
>
> int *alloczero() {
> int *p = malloc(sizeof *p);
>
> if (*p)
> *p = 0;
> return p;
> }
>
> valgrind reports 'conditional jump..'
> at line 'if (*p)', which is correct
> and easy to suppress
>
> but later whereever i read *p i get
> '..uninitialised' value errors
> eventhough it's clearly provably 0
Really? Can you send a complete test program that demonstrates this?
J
|
|
From: Julian S. <js...@ac...> - 2011-07-01 07:20:15
|
> Really? Can you send a complete test program that demonstrates this? Oh, I didn't read it carefully enough. Ignore that. I'll get another coffee. J |