Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is this a Visual Studio 2013 update 4 C++ optimizer bug or is my code wrong?

I have been seeing crashes in our software since I updated to boost 1.58 and VS2013. Only when compiler optimization is on we see that crashes. With boost 1.55 there are no crashes. I've managed to isolate the problem I'm seeing to boost::any_range and how we use it.

See the example code below:

#include <boost/range/any_range.hpp>
#include <boost/range/adaptor/transformed.hpp>
#include <vector>
#include <memory>
#include <cstdio>

class DummyElement
{
public:
    float f_;
};

using ElementRange = boost::any_range < DummyElement*, boost::bidirectional_traversal_tag >;

using DummyElementUPtr = std::unique_ptr < DummyElement > ;

class BoostAnyTest
{
public:
    BoostAnyTest()
    { 
        for (int i = 0; i < 10; ++i)
        {
            auto element = DummyElementUPtr(new DummyElement());
            _tprintf(_T("BoostAnyTest::ctor() 0x%p\n"), element.get());

            c_.emplace_back(std::tuple<Int, DummyElementUPtr>(i, std::move(element)));
        }
    }

public:
    ElementRange GetAll();

private:
    using _ContainerType = std::vector < std::tuple<Int, std::unique_ptr<DummyElement>> > ;
    _ContainerType    c_;
};


ElementRange
BoostAnyTest::GetAll()
{
    auto transform = [ ] (const _ContainerType::value_type& v) -> DummyElement*
    {
        return std::get<1>(v).get();
    };

    return c_ | boost::adaptors::transformed(transform);
}


int
main()
{
    BoostAnyTest    any;

    auto range = any.GetAll();

    std::for_each(std::begin(range), std::end(range), [ ] (DummyElement* element)
    { 
        _tprintf(_T("TestBoostAnyRange() 0x%p\n"), element);
    });
}

Below is the program output. The DEBUG version output is what I expect, but the optimized RELEASE version is a mistery to me at the moment...

DEBUG version output:
BoostAnyTest::ctor() 0x007D0FB0
BoostAnyTest::ctor() 0x007D0E30
BoostAnyTest::ctor() 0x007D0E60
BoostAnyTest::ctor() 0x007D1160
BoostAnyTest::ctor() 0x007D0E90
BoostAnyTest::ctor() 0x007D10A0
BoostAnyTest::ctor() 0x007D0F80
BoostAnyTest::ctor() 0x007D0FE0
BoostAnyTest::ctor() 0x007D1010
BoostAnyTest::ctor() 0x007D1040
TestBoostAnyRange() 0x007D0FB0
TestBoostAnyRange() 0x007D0E30
TestBoostAnyRange() 0x007D0E60
TestBoostAnyRange() 0x007D1160
TestBoostAnyRange() 0x007D0E90
TestBoostAnyRange() 0x007D10A0
TestBoostAnyRange() 0x007D0F80
TestBoostAnyRange() 0x007D0FE0
TestBoostAnyRange() 0x007D1010
TestBoostAnyRange() 0x007D1040

RELEASE version output:
BoostAnyTest::ctor() 0x00BFA358
BoostAnyTest::ctor() 0x00BFA238
BoostAnyTest::ctor() 0x00BFA3E8
BoostAnyTest::ctor() 0x00BFA248
BoostAnyTest::ctor() 0x00BFA258
BoostAnyTest::ctor() 0x00BFA268
BoostAnyTest::ctor() 0x00C2ECB8
BoostAnyTest::ctor() 0x00C2ED98
BoostAnyTest::ctor() 0x00C2EDA8
BoostAnyTest::ctor() 0x00C2ED48
TestBoostAnyRange() 0x00A5FCE0
TestBoostAnyRange() 0x00A5FCE0
TestBoostAnyRange() 0x00A5FCE0
TestBoostAnyRange() 0x00A5FCE0
TestBoostAnyRange() 0x00A5FCE0
TestBoostAnyRange() 0x00A5FCE0
TestBoostAnyRange() 0x00A5FCE0
TestBoostAnyRange() 0x00A5FCE0
TestBoostAnyRange() 0x00A5FCE0
TestBoostAnyRange() 0x00A5FCE0

Maybe my code is wrong or is it really a bug in the optimizer? Any tips would be greatly appreciated!

like image 932
Jormungand999 Avatar asked Jul 14 '15 09:07

Jormungand999


1 Answers

This is Boost bug 10493 (introduced in Boost 1.56, which is why your code works with Boost 1.55).

The workaround is to use T const as the Reference template parameter, in your case:

using ElementRange = boost::any_range <
    DummyElement*,
    boost::bidirectional_traversal_tag,
    DummyElement* const
>;

Example.

like image 191
ecatmur Avatar answered Nov 11 '22 20:11

ecatmur