Boost logo

Boost Users :

Subject: Re: [Boost-users] [Multiprecision] Runtime assertion failure with clang++3.6.0 but not g++4.9.2
From: Jeff Schwab (jeff_at_[hidden])
Date: 2016-02-08 13:51:34


Seems to be that Multiprecision relies on static data that haven't
(necessarily) been initialized before your own static members. Works fine
if the members are made non-static:

#include <iostream>
#include <boost/multiprecision/gmp.hpp>

namespace bm = boost::multiprecision;

template <std::size_t N>
struct factorial2
{
    const bm::mpz_int value = N * factorial2<N-1>().value;
};

template<>
struct factorial2<0>
{
    const bm::mpz_int value = 1;
};

int main()
{
    std::cout << factorial2<3>().value << '\n';
    return 0;
}

On Mon, Feb 8, 2016 at 10:58 AM, <mbw_bst_at_[hidden]> wrote:

> Dear all,
>
> this is my first post on this mailing list, so hopefully this will all be
> by the book.
> Executing the following minimal working example, which is supposed to
> calculate "3! == 6" via
> (1) a template function
> (2) a class template
>
> and save the result in a boost::multiprecision::mpz_int, results in
> unexpected behavior for clang++3.6.0,
> with the version of my boost library being 1.59.0.
>
> The program displays the correct result using g++4.9.2 however:
>
>
> #include <iostream>
> #include <boost/multiprecision/gmp.hpp>
>
> namespace bm = boost::multiprecision;
>
> template <std::size_t N>
> bm::mpz_int factorial()
> {
> return N * factorial<N-1>();
> }
>
> template<>
> bm::mpz_int factorial<0>()
> {
> return 1;
> }
>
> template <std::size_t N>
> struct factorial2
> {
> static const bm::mpz_int value;
> };
> template<std::size_t N>
> const bm::mpz_int factorial2<N>::value = N * factorial2<N-1>::value;
>
> template<>
> struct factorial2<0>
> {
> static const bm::mpz_int value;
> };
> const bm::mpz_int factorial2<0>::value = 1;
>
> int
> main ()
> {
> std::cout << factorial<3>() << '\n';
> std::cout << factorial2<3>::value << '\n';
> return 0;
> }
>
> The output for clang, having been compiled via
>
> clang++ -std=c++14 -stdlib=libc++ -DNDEBUG -o main main.cpp -lgmp
>
> will result in:
>
> 6
> 0
>
> However, omitting the NDEBUG flag will trigger an assertion failure:
>
> main: /usr/include/boost/multiprecision/gmp.hpp:1296: const mpz_t
> &boost::multiprecision::backends::gmp_int::data() const: Assertion
> `m_data[0]._mp_d' failed.
> Aborted (core dumped)
>
> Compiling the same program with g++4.9.2 (with or without "-DNDEBUG")
> yields the expected result:
>
> 6
> 6
>
> What did I miss? Can this behavior indeed be traced down to
> Boost.Multiprecision, or does it have to do with the initialization order
> of static const class members? Or something else?
> Additionally, both variants work correctly with clang when using a
> built-in type like 'int'.
>
> Any help in understanding the problem on hand would be greatly
> appreciated!
>
>
> Best Regards,
>
> mbw
> _______________________________________________
> Boost-users mailing list
> Boost-users_at_[hidden]
> http://lists.boost.org/mailman/listinfo.cgi/boost-users
>



Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net