Opened 8 years ago
Last modified 5 years ago
#10005 reopened Bugs
erf_inv_initializer crashes under valgrind
Reported by: | Owned by: | John Maddock | |
---|---|---|---|
Milestone: | To Be Determined | Component: | math |
Version: | Boost 1.54.0 | Severity: | Problem |
Keywords: | Cc: |
Description
It was reported before on the mailing list: http://lists.boost.org/boost-users/2012/08/75711.php and I assume it's because valgrind doesn't support long doubles: https://bugs.kde.org/show_bug.cgi?id=197915
Somehow erfc_inv is called in this place and the argument is then found to be 0:
// Some compilers choke on constants that would underflow, even in code that isn't instantiated // so try and filter these cases out in the preprocessor: #if LDBL_MAX_10_EXP >= 800 if(static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1e-800)) != 0) boost::math::erfc_inv(static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1e-800)), Policy());
So an exception is thrown during initialization. While it may not be a bug, valgrind is extremely useful and it would be nice to have a workaround.
I don't understand why erf_inv and erfc_inv are called with these arguments in erf_inv_initializer<>::init::do_init()
, so I'm not sure what workaround is safe.
Here is a full traceback:
#0 0x00000036fb435c39 in __GI_raise (sig=sig@entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56 #1 0x00000036fb437348 in __GI_abort () at abort.c:89 #2 0x00000036ff860f85 in __gnu_cxx::__verbose_terminate_handler () at ../../../../libstdc++-v3/libsupc++/vterminate.cc:95 #3 0x00000036ff85eee6 in __cxxabiv1::__terminate (handler=<optimized out>) at ../../../../libstdc++-v3/libsupc++/eh_terminate.cc:38 #4 0x00000036ff85ef13 in std::terminate () at ../../../../libstdc++-v3/libsupc++/eh_terminate.cc:48 #5 0x00000036ff85f13f in __cxxabiv1::__cxa_throw (obj=0x526e490, tinfo=<optimized out>, dest=<optimized out>) at ../../../../libstdc++-v3/libsupc++/eh_throw.cc:84 #6 0x0000000004cb1541 in boost::throw_exception<std::overflow_error> (e=...) at /usr/include/boost/throw_exception.hpp:67 #7 0x0000000004cb7f28 in boost::math::policies::detail::raise_error<std::overflow_error, long double> ( function=0x4d2d338 "boost::math::erfc_inv<%1%>(%1%, %1%)", message=0x4d1bf8e "Overflow Error") at /usr/include/boost/math/policies/error_handling.hpp:95 #8 0x0000000004cb7f98 in boost::math::policies::detail::raise_overflow_error<long double> (function=<optimized out>, message=<optimized out>) at /usr/include/boost/math/policies/error_handling.hpp:211 #9 0x0000000004cdf17e in raise_overflow_error<long double, boost::math::policies::policy<boost::math::policies::promote_float<false>, boost::math::policies::promote_double<false>, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy> > (message=0x0, function=<optimized out>) at /usr/include/boost/math/policies/error_handling.hpp:515 #10 boost::math::erfc_inv<long double, boost::math::policies::policy<boost::math::policies::promote_float<false>, boost::math::policies::promote_double<false>, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy> > (z=0, z@entry=0, pol=...) at /usr/include/boost/math/special_functions/detail/erf_inv.hpp:383 #11 0x0000000004cdfaae in boost::math::detail::erf_inv_initializer<long double, boost::math::policies::policy<boost::math::policies::promote_float<false>, boost::math::policies::promote_double<false>, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy> >::init::do_init () at /usr/include/boost/math/special_functions/detail/erf_inv.hpp:347 #12 0x0000000004cda34b in init (this=<optimized out>) at /usr/include/boost/math/special_functions/detail/erf_inv.hpp:332 #13 __static_initialization_and_destruction_0 ( __initialize_p=__initialize_p@entry=1, __priority=__priority@entry=65535) at /usr/include/boost/math/special_functions/detail/erf_inv.hpp:367 #14 0x0000000004cda463 in _GLOBAL__sub_I_fit.cpp(void) () at ../../fityk/fit.cpp:643 #15 0x00000036fb00f2ea in call_init (l=<optimized out>, argc=argc@entry=1, argv=argv@entry=0xffefffc48, env=env@entry=0xffefffc58) at dl-init.c:82 #16 0x00000036fb00f3d3 in call_init (env=<optimized out>, argv=<optimized out>, argc=<optimized out>, l=<optimized out>) at dl-init.c:34 #17 _dl_init (main_map=0x36fb221168, argc=1, argv=0xffefffc48, env=0xffefffc58) at dl-init.c:130 #18 0x00000036fb00122a in _dl_start_user () from /lib64/ld-linux-x86-64.so.2
Change History (18)
comment:1 by , 8 years ago
comment:2 by , 8 years ago
Update: I just experimented with this, and I'm unable to reproduce with current Git master and valgrind-3.8.1. Do you have a reduced test case?
comment:3 by , 8 years ago
I haven't realized it before, but it depends on compiler flags.
I'm using now Fedora 20, valgrind 3.9.0, GCC 4.8 and boost 1.54 and 1.55 (both give the same result).
I can reproduce the problem only with g++ -Og
.
But I've seen it with previous GCC versions (4.6 or 4.7, I'm not sure) and valgrind 3.8.1.
I don't remember what optimization flags I used, but there was no -Og
in previous versions.
The minimal program I now use for testing is:
#include <stdio.h> #include <stdlib.h> #include <boost/math/special_functions.hpp> int main(int argc, char **argv) { double x = strtod(argv[1], NULL); printf("%g\n", boost::math::erfc_inv(x)); }
So as a workaround I'll just use a different compilation flags.
comment:4 by , 8 years ago
Resolution: | → fixed |
---|---|
Status: | new → closed |
It does indeed seem to be specific to using -Og. After a bit of experimentation I believe I have it fixed in https://github.com/boostorg/math/commit/a29a74bdaf078b5df4f875ead18960671fd5c479
comment:5 by , 7 years ago
I am experiencing this on Ubuntu 12.04 (valgrind-3.7.0 and gcc 4.6.3) with a manually installed Boost 1.58.0.
terminate called after throwing an instance of 'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<std::overflow_error> >' what(): Error in function boost::math::erfc_inv<long double>(long double, long double): Overflow Error
It occurs when either the -O3
or -O2
flag is given, but does not occur without an -O
flag. I didn't test any other optimization flag combinations.
comment:6 by , 7 years ago
Sigh... I'll look into this again, but no promises, long double floating point values seem to behave completely unpredictably under valgrind :(
comment:7 by , 7 years ago
I was hit by this problem using Ubuntu 15.10 LTS on x86-64, which ships with boost 1.58.0 and GCC 5.2.1. For me, this problem exists only when my program is compiled by using -O2 -g. It ran ok under valgrind when compiled without -O2. I guess GCC removes is_value_non_zero() during optimization.
follow-up: 9 comment:8 by , 7 years ago
Resolution: | fixed |
---|---|
Status: | closed → reopened |
I am getting this under boost version 1.54.0.1 installed from apt-get on Mint 17.2. Compiled with clang 3.4. Still occurs when no build flags are specified.
follow-up: 10 comment:9 by , 7 years ago
Replying to scott_paulin@…:
I am getting this under boost version 1.54.0.1 installed from apt-get on Mint 17.2. Compiled with clang 3.4. Still occurs when no build flags are specified.
Update: Works fine when I compile my code WITHOUT -std=c++11
comment:10 by , 7 years ago
Replying to anonymous:
Replying to scott_paulin@…:
I am getting this under boost version 1.54.0.1 installed from apt-get on Mint 17.2. Compiled with clang 3.4. Still occurs when no build flags are specified.
Update: Works fine when I compile my code WITHOUT -std=c++11
Sorry, the first message should have read "Still occurs when no -O build flags are specified". I can't edit that message, it would be cool if someone with admin rights could clean up my mess by editing my first message.
comment:11 by , 7 years ago
Boost-1.54 is an old Boost release now - and precedes the fixes (such as they are) above. Can you please try with Boost-1.60?
comment:12 by , 7 years ago
I'm unable to reproduce on ubuntu with any combination of -ON and -g and either latest clang or gcc-5.1 or 4.9.2 and current develop branch (which should be the same as 1.60). Which is not to say that some folks won't experience this still.
The essential issue is that valgrind doesn't support long double fully, so finite long doubles can get truncated to zero or infinity and random points in the program (ie you can check that a variable is non-zero, and then in the next line when you go to actually use it, it's been magically truncated to zero. The result is that it completely breaks program logic).
There are a couple of possible workarounds (other than choosing -O options carefully), to define:
BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS - which prevents any long double functions from being defined or used with Boost.Math, or else define: BOOST_MATH_PROMOTE_DOUBLE_POLICY=false, which prevents double functions from being evaluated at long double precision internally, but otherwise retains the long double implementations if they're needed.
Both of these will reduce precision slightly, and both will typically improve performance on 64-bit hardware.
comment:15 by , 5 years ago
I'm unable to reproduce, I tried every combination of -std= and -O options I could think of with gcc-4.8.4, 6.1.0 and clang-5.
Can you provide an updated test case along with the build options and compiler version used?
comment:16 by , 5 years ago
Reproduced under Ubuntu 17.04
$ valgrind --version
valgrind-3.13.0
$ gcc --version
gcc (Ubuntu 7.2.0-1ubuntu2) 7.2.0
I use both -std=c++11 and -O2 flags and valgrind works fine if I remove the -O flag
comment:17 by , 5 years ago
I appear to have this with valgrind 3.10.1, and Boost 1.63.0, compiled with GCC 7.2.0 on Ubuntu 14.04.5.
I'm not sure what compiler flags i'm using: Boost is a dependency of a third-party library whose build process is an impenetrable thicket.
Oh boy this sucks :-(
You could work around the problem by defining BOOST_MATH_PROMOTE_DOUBLE_POLICY=false when building I guess.
I don't really understand why this is being triggered, the code checks that 1e-800 is non-zero before calling erc_inv(1e-800) at which point it apparently is zero after all! The argument values can't be changed BTW - they're cunningly chosen to take specific code paths and force initialization of all the static data. Or I could add some try/catch blocks I guess, I will probably experiment with that.