2015-07-14 2 views
8

J'ai vu des plantages dans notre logiciel depuis que j'ai mis à jour pour booster 1.58 et VS2013. Ce n'est que lorsque l'optimisation du compilateur est activée que nous voyons des plantages. Avec boost 1.55 il n'y a pas de crash. J'ai réussi à isoler le problème que je vois à boost::any_range et comment nous l'utilisons.Est-ce un bogue de l'optimiseur C++ de mise à jour Visual Studio 2013 4 ou mon code est-il incorrect?

Voir l'exemple de code ci-dessous:

#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); 
    }); 
} 

Voici la sortie du programme. La sortie de la version DEBUG est ce que je pense, mais la version optimisée est un mystère pour moi en ce 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 

Peut-être que mon code est erroné ou est-ce vraiment un bogue dans l'optimiseur? Tous les conseils seraient grandement appréciés!

+2

'_ContainerType' est un nom réservé (car il commence par un trait de soulignement suivi d'une lettre majuscule). Pas lié à votre problème, cependant. – dyp

+2

Ne ressemble pas à un bogue du compilateur: http://coliru.stacked-crooked.com/a/edcdb838034085ca – dyp

+3

Veuillez présenter un testcase minimal compilable. Il aurait une fonction 'main'. Aussi ... allumez vos avertissements de compilateur !!!!!!!!!!!!!! –

Répondre

11

Ceci est Boost bug 10493 (introduit dans Boost 1.56, c'est pourquoi votre code fonctionne avec Boost 1.55).

La solution consiste à utiliser T const comme paramètre de modèle Reference, dans votre cas:

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

Example.

+0

Merci beaucoup à tous pour cette question et pour vos réponses et suggestions! – Jormungand999