【问题标题】:How to throw exception for out of bounds write with std::transform?如何使用 std::transform 为越界写入抛出异常?
【发布时间】:2017-06-24 14:30:32
【问题描述】:

我有以下代码将std::vector a 复制到另一个std::vector b,但以2 作为起始索引。由于两个向量的长度都是 4,这会导致写入越界。我想让这段代码抛出异常,但我该怎么做呢?下面的代码因分段错误而崩溃。

#include <vector>
#include <iostream>

int main()
{
    std::vector<double> a = {1, 2, 3, 4};
    std::vector<double> b(4);

    try
    {
        std::transform(a.begin(), a.begin()+4, b.begin()+2,
                [](const double d) { return d; });
    }
    catch (std::exception& e)
    {
        std::cout << "EXCEPTION: " << e.what() << std::endl;
        return 1;
    }

    return 0;
}

【问题讨论】:

  • 与您的问题无关,但如果您所做的只是将一个向量复制到另一个向量,为什么要使用std::transform 而不是std::copy
  • 用例有点复杂,因为我在 lambda 函数中转换类型。我遇到了这个问题,并做了一个最简单的例子来说明我的问题。

标签: c++ c++11 exception exception-handling std


【解决方案1】:

std::transform 假设 [d_first, d_first+std::distance(first1, last1)) 是有效的。

但是你可以编写自己的算法,如果你也添加一个“结束”迭代器到输出范围:

template <typename InputIt, typename OutputIt, typename UnaryOp>
OutputIt safe_transform(
   InputIt first1, InputIt last1,
   OutputIt first2, OutputIt last2,
   UnaryOp unary_op )
{
    while ( first1 != last1 ) {
        if ( first2 == last2 )
            throw std::domain_error( "Reached end of output range" );
        *first2 = unary_op( *first1 );
        ++first1;
        ++first2;
    }
    return first2;
}

【讨论】:

    【解决方案2】:

    transform 在底层取消引用它的迭代器。没有任何方法可以让它调用at(),这是operator[] 的边界检查版本。您可以使用-D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC 启用调试容器,其中 libstdc++ 将使用“安全迭代器”,如果您迭代越界则终止程序。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-30
      • 1970-01-01
      相关资源
      最近更新 更多