Valgrind false positive in make_shared
Hi Folks I've been tracking down some almost-certainly-false-positives from Valgrind. Consider the following code: #include <iostream> #include <boost/shared_ptr.hpp> #include <boost/make_shared.hpp> using namespace std; using boost::make_shared; struct StateSpace { public: StateSpace(int spaceType) { if (spaceType == 4) cout << "Some Output" << endl; } }; class State { public: State() : m_rep(make_shared<StateSpace>(0) ) {} boost::shared_ptr<StateSpace> m_rep; }; int main() { State state; } Valgrind 3.6 reports this: ==8198== Memcheck, a memory error detector ==8198== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al. ==8198== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info ==8198== Command: testState ==8198== ==8198== Conditional jump or move depends on uninitialised value(s) ==8198== at 0x401659: StateSpace::StateSpace(int) (testState.cpp:14) ==8198== by 0x401796: boost::shared_ptr<StateSpace> boost::make_shared<StateSpace, int, >(int&&, ) (make_shared.hpp:150) ==8198== by 0x4016BD: State::State() (testState.cpp:22) ==8198== by 0x401317: main (testState.cpp:29) ==8198== ==8198== ==8198== HEAP SUMMARY: ==8198== in use at exit: 464 bytes in 5 blocks ==8198== total heap usage: 240 allocs, 236 frees, 45,162 bytes allocated ==8198== ==8198== LEAK SUMMARY: ==8198== definitely lost: 0 bytes in 0 blocks ==8198== indirectly lost: 0 bytes in 0 blocks ==8198== possibly lost: 0 bytes in 0 blocks ==8198== still reachable: 464 bytes in 5 blocks ==8198== suppressed: 0 bytes in 0 blocks ==8198== Reachable blocks (those to which a pointer was found) are not shown. ==8198== To see them, rerun with: --leak-check=full --show-reachable=yes ==8198== ==8198== For counts of detected and suppressed errors, rerun with: -v ==8198== Use --track-origins=yes to see where uninitialised values come from ==8198== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 5 from 5) Interestingly, if I change State() : m_rep(make_shared<StateSpace>(0) ) {} to State() : m_rep(new StateSpace(0)) {} the Valgrind error goes away. This is, of course, a greatly boiled-down version of our actual code, which we're very confident works correctly. Any ideas about why Valgrind doesn't like the call to make_shared? Any ideas about how to silence this warning (other than adding it to Valgrind's suppressions file)? Thanks very much. -- Dave Steffen, Ph.D. - Software Engineer Numerica Corporation <http://www.numerica.us> 4850 Hahns Peak Drive, Suite 200 Loveland, Colorado 80538 main (970) 461-2000 x 227 direct (970) 612-2327 Email: dave.steffen@numerica.us fax (970) 461-2004
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Tuesday 16 November 2010, Dave Steffen wrote:
==8198== Conditional jump or move depends on uninitialised value(s) ==8198== at 0x401659: StateSpace::StateSpace(int) (testState.cpp:14) ==8198== by 0x401796: boost::shared_ptr<StateSpace> boost::make_shared<StateSpace, int, >(int&&, ) (make_shared.hpp:150) ==8198== by 0x4016BD: State::State() (testState.cpp:22) ==8198== by 0x401317: main (testState.cpp:29)
Any ideas about why Valgrind doesn't like the call to make_shared?
It looks like it might be a bug in make_shared's perfect forwarding when compiling in c++0x mode. When I compile your example I get a warning: $ g++ -Wall -g -std=c++0x -I ~/svn/boost_trunk/ make_shared_valgrind.cpp /svn/boost_trunk/boost/smart_ptr/make_shared.hpp: In function ‘T&& boost::detail::sp_forward(T&) [with T = int]’: /svn/boost_trunk/boost/smart_ptr/make_shared.hpp:150: instantiated from ‘boost::shared_ptr<X> boost::make_shared(Arg1&&, Args&& ...) [with T = StateSpace, Arg1 = int, Args = ]’ make_shared_valgrind.cpp:21: instantiated from here /svn/boost_trunk/boost/smart_ptr/make_shared.hpp:93: warning: returning reference to temporary
Any ideas about how to silence this warning (other than adding it to Valgrind's suppressions file)?
Not forwarding a literal constant works: class State { public: State() : m_rep(make_shared<StateSpace>(spaceType) ) {} static const int spaceType; boost::shared_ptr<StateSpace> m_rep; }; const int State::spaceType = 0; -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (GNU/Linux) iEYEARECAAYFAkzi1boACgkQ5vihyNWuA4Xq9ACggT4DQr/HzkdDTFt0na0yGLqW TLEAoKtyB8VZy61d2Ug0X8eatHjoFDsu =JMjU -----END PGP SIGNATURE-----
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Tuesday 16 November 2010, Frank Mori Hess wrote:
It looks like it might be a bug in make_shared's perfect forwarding when compiling in c++0x mode.
Another bit of info: getting rid of the static_cast in boost::detail::sp_forward makes both the compiler warning and valgrind error go away, although I have no idea why. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (GNU/Linux) iEYEARECAAYFAkzi5TwACgkQ5vihyNWuA4UcUgCaAzrGpRsNwELdj6AxoOWQszVp KrwAoItTgtPc0pqyPnY+Ztq3oC/QG6GY =3/MC -----END PGP SIGNATURE-----
Frank Mori Hess wrote:
Another bit of info: getting rid of the static_cast in boost::detail::sp_forward makes both the compiler warning and valgrind error go away, although I have no idea why.
Interesting... which version of GCC? Without the static_cast, it shouldn't compile, as rvalue references no longer bind to lvalues. In fact, I see that I added the static_cast in [61574] for that very reason.
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Tuesday 16 November 2010, Peter Dimov wrote:
Interesting... which version of GCC? Without the static_cast, it shouldn't compile, as rvalue references no longer bind to lvalues. In fact, I see that I added the static_cast in [61574] for that very reason.
$ gcc --version gcc (Debian 4.3.2-1.1) 4.3.2 Its implementation of std::forward looks like: template<typename _Tp> inline _Tp&& forward(typename std::identity<_Tp>::type&& __t) { return __t; } -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (GNU/Linux) iEYEARECAAYFAkzj51EACgkQ5vihyNWuA4WP8QCg3kIa/TqBzQl4JDGnbUKkeAKT Z9UAoIeNJmodVJu6V8JxH/WhnEMi5rf4 =b8yU -----END PGP SIGNATURE-----
Frank Mori Hess wrote:
On Tuesday 16 November 2010, Peter Dimov wrote:
Interesting... which version of GCC? Without the static_cast, it shouldn't compile, as rvalue references no longer bind to lvalues. In fact, I see that I added the static_cast in [61574] for that very reason.
$ gcc --version gcc (Debian 4.3.2-1.1) 4.3.2
Its implementation of std::forward looks like:
template<typename _Tp> inline _Tp&& forward(typename std::identity<_Tp>::type&& __t) { return __t; }
So it appears that we need to revert to the old forward for 4.3 and earlier. The easiest would be to just use std::forward, but unfortunately, I remember that some earlier versions of the standard library didn't have it. :-/
participants (3)
-
Dave Steffen
-
Frank Mori Hess
-
Peter Dimov