Valgrind and its associated tools do not treat long doubles any different than doubles. Take, for example, this little program: ------------------- #include <iostream> int main () { long double x = 1.+1e-14; for (unsigned int i=0; i<10; ++i) { x = static_cast<long double>(1.)+(x-1)/2; std::cout << x-1 << std::endl; } } ------------------ When compiled and run on an opteron box with gcc 3.3.5, I get this: spec/src> c++ y.cc spec/src> ./a.out 4.996e-15 2.498e-15 1.249e-15 6.245e-16 3.1225e-16 1.56125e-16 7.80626e-17 3.90313e-17 1.95156e-17 9.75782e-18 spec/src> valgrind ./a.out ==7430== Memcheck, a memory error detector. ==7430== Copyright (C) 2002-2005, and GNU GPL'd, by Julian Seward et al. ==7430== Using LibVEX rev 1471, a library for dynamic binary translation. ==7430== Copyright (C) 2004-2005, and GNU GPL'd, by OpenWorks LLP. ==7430== Using valgrind-3.1.0, a dynamic binary instrumentation framework. ==7430== Copyright (C) 2000-2005, and GNU GPL'd, by Julian Seward et al. ==7430== For more details, rerun with: -v ==7430== 4.88498e-15 2.44249e-15 1.33227e-15 6.66134e-16 4.44089e-16 2.22045e-16 0 0 0 0 ==7430== ==7430== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 8 from 5) ==7430== malloc/free: in use at exit: 0 bytes in 0 blocks. ==7430== malloc/free: 0 allocs, 0 frees, 0 bytes allocated. ==7430== For counts of detected errors, rerun with: -v ==7430== No malloc'd blocks -- no leaks are possible. Note the difference in output! The problem with this is, of course, that it leads to algorithms that converge when run on the command line, but loop forever when run under valgrind. Best Wolfgang
> Valgrind and its associated tools do not treat long doubles any > different than doubles. That's true. It's a documentated limitation: http://www.valgrind.org/docs/manual/manual-core.html#manual-core.limits > The problem with this is, of course, that it leads to algorithms that > converge when run on the command line, but loop forever when run under > valgrind. It also means your program is inherently unportable - you have no chance of it working on ppc, nor if you compile it to use SSE on x86/amd64 for example if it was vectorised.
> It also means your program is inherently unportable Not really. What it means is that gcc+valgrind does not implement C99. Take this program, for example: #include <stdio.h> #include <float.h> #include <assert.h> int main (int argc, char **argv) { long double ld = argc * LDBL_MIN; printf ("%Lg\n", ld); assert (ld > 0); return 0; } When you run that with no arguments, argc==1, then C99 guarantees that the program will print a positive number and exit cleanly. Under valgrind, it instead prints zero and aborts. (I don't have the c++ standard handy, but I'm sure it says something of the same nature.) That Valgrind does not handly this is all clearly documented, but please don't blame it on the subject program.
> It also means your program is inherently unportable - you have no chance > of it working on ppc I think this is an unfair characterization. It may be true that one shouldn't be using things like long double eps = 1e-19; and test for that as a convergence criterion. But what people do in their codes is stuff like long double eps = std::numeric_limits<long double>::eps(); This *is* portable, but leads to different behavior in algorithms when run freestanding and under valgrind on x86. > nor if you compile it to use SSE on x86/amd64 > for example if it was vectorised. That's also not quite correct since long double variables can't be vectorized anyway. Either way, the point I wanted to make is not so much whether the example program I showed is good or bad style (it's a reduced testcase, not part of a portable program) but that with this program we get different behavior for a program depending on whether it is run under valgrind or not. That's certainly an undesirable feature. Thanks Wolfgang
Created attachment 32672 [details] program that behaves differently under valgrind Here is another program that behaves differently under valgrind than natively. Natively: 1020 5.61779e+306 1020 0.5 1021 1.12356e+307 1021 0.5 1022 2.24712e+307 1022 0.5 1023 4.49423e+307 1023 0.5 1024 8.98847e+307 1024 0.5 1025 1.79769e+308 1025 0.5 1026 3.59539e+308 1026 0.5 1027 7.19077e+308 1027 0.5 1028 1.43815e+309 1028 0.5 Under "valgrind --tool=memcheck" (on AMD64): 1020 5.61779e+306 1020 0.5 1021 1.12356e+307 1021 0.5 1022 2.24712e+307 1022 0.5 1023 4.49423e+307 1023 0.5 1024 8.98847e+307 1024 0.5 1025 inf 0 inf This program is not unportable; it is part of the gnulib testsuite and known to succeed on all platforms. The problem is that valgrind appears to assume a different format for 'long double', which does not match the constants in <float.h>.
> This program is not unportable; it is part of the gnulib testsuite and known > to succeed on all platforms. What does "succeed" mean in this context? "Produces identical results on all platforms?" FWIW, here's the output on openSUSE 10.3 on ppc32 (running natively): 1020 5.61779e+306 1020 0.5 1021 1.12356e+307 1021 0.5 1022 2.24712e+307 1022 0.5 1023 4.49423e+307 1023 0.5 1024 8.98847e+307 1024 0.5
*** This bug has been marked as a duplicate of bug 179915 ***
*** This bug has been marked as a duplicate of bug 197915 ***