boost :: any_range< gsl :: string_span<>在发布模式下崩溃 [英] boost::any_range<gsl::string_span<>> crash in Release mode

查看:125
本文介绍了boost :: any_range< gsl :: string_span<>在发布模式下崩溃的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在观察以下代码的相当奇怪的行为:

I'm observing a rather weird behaviour of the following piece of code:

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

#include <vector>
#include <string>
#include <iostream>

#include "gsl.h"

template <typename T>
using ImmutableValueRange = boost::any_range<T, boost::bidirectional_traversal_tag, /*const*/ T>;

template <typename T, typename C>
ImmutableValueRange<T> make_transforming_immutable_range(const C& container)
{
    return container | boost::adaptors::transformed([](const typename C::value_type& v) -> T 
    {
        //std::cout << "trans : " << T{ v }.data() << "\n";
        return T{ v }; 
    });
}

void f(ImmutableValueRange<gsl::cstring_span<>> r)
{
    for (const auto& c : r) {
        std::cout << c.data() << "\n";
    }
}

int main()
{
    std::vector<std::string> v({ "x", "y", "z" });

    f(make_transforming_immutable_range<gsl::cstring_span<>>(v));
}

这里的想法是隔离由any_rangegsl::string_span后面的函数f作为参数接收的字符串序列的实际表示(请注意,将string_view更改为已于两个小时前到达GSL.

The idea here is to isolate the actual representation of a sequence of strings that is received as a parameter by the function f behind an any_range and gsl::string_span (note, the commit changing string_view to string_span has been made a couple of hours ago to GSL).

我的原始代码没有const T作为any_rangeReference模板参数(这是一个简单的T),并且在执行过程中崩溃了.但是,这仅在发布模式下发生,在Debug或RelWithDebInfo(由CMake生成)中可以正常工作.我使用VS2013/2015 x64.此外,尝试调试完整的Release版本,将调试输出添加到转换lambda可以消除崩溃(我想这是可以防止某些内联的).我最后的工作解决方案是将const T指定为Reference.

My original code did not have a const T as Reference template parameter to any_range (it was a simple T) and it crashed during execution. However, that happened only in Release mode an worked fine in Debug or RelWithDebInfo (generated by CMake). I used VS2013/2015 x64. Furthermore, trying to debug the full Release version, adding debug output to the conversion lambda eliminated the crash (my guess is it prevented some inlining). My final working solution is to specify const T as Reference.

但是,我仍然想知道为什么首先发生崩溃?是VS编译器错误吗?当前string_span实现中的错误?还是我只是滥用boost::any_range?

However, I'm still wondering why did the crash happen in the first place? Is it the VS compiler bug? Bug in the current implementation of string_span? Or am I simply misusing the boost::any_range?

修改

仅使用clang 3.7.0构建了该版本,其行为类似(在调试中工作正常,不会崩溃,但是在不带const T-O2的情况下输出垃圾).因此,这似乎不像是编译器问题.

Just built the version with clang 3.7.0 and the behaviour is similar (works fine in debug and doesn't crash, but outputs garbage without const T with -O2). So it doesn't seem like a compiler problem.

推荐答案

事实证明,除非将Reference类型指定为any_range,否则any_rangedereference方法将返回对T的引用. c5>,从而创建对临时对象的悬空引用.发生这种情况是由于使用了 any_iterator_interface中定义的any_incrementable_iterator_interface::mutable_reference_type_generator. hpp .

As it turns out, the any_range's dereference method will return a reference to T unless the Reference type is specified as const T, thus creating a dangling reference to a temporary. This happens due to use of any_incrementable_iterator_interface::mutable_reference_type_generator defined in any_iterator_interface.hpp.

因此,对该问题的正确解决方案的确是在迭代器取消引用返回临时值的情况下将const T指定为Reference类型.

Therefore, the correct solution to the problem is indeed to specify const T as the Reference type in case the iterator dereferencing returns a temporary.

这篇关于boost :: any_range&lt; gsl :: string_span&lt;&gt;在发布模式下崩溃的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆