std :: vector segfaulting而不是抛出异常



我正在尝试为std::vector创建一个容器类,以教会自己对模板,超载操作员和管理异常的更多信息。

目前,我只是在定义基本操作。我有下面列出的模板类;我已经将+=[]运算符重载到push_back vector使用T,并分别直接访问向量的元素。这是按预期工作的。

+=运算符执行应做的事情,并且尝试在元素上使用[]操作员将按预期抛出异常。

这是当前所处的原型类和实现:

#include <iostream>
#include <vector>
#include <string>
using namespace std;
template <class T>
class Inventory
{
    public:
        void operator += (const T& b)   { backpack.push_back(b); }
        T operator [] (const unsigned& b)
        {
            if (backpack.empty() || backpack.size() < b)
                throw string("Out of Range");
            return backpack[b];
        }
        void operator -= (const unsigned& b)
        {
            if (backpack.empty() || backpack.size() < b)
                throw string("No such element exists.");
            backpack.erase(backpack.begin() + b);
        }
    private:
        vector<int> backpack;
};
int main()
{
    Inventory<int> pack;
    pack += 2;
    pack += 4;
    try
    {
        cout << "It was " << pack[0] << endl;
        cout << "It was " << pack[1] << endl;
        pack -= 0;
        cout << "It is now " << pack[0] << endl;
        //pack -= 1; // Segfaults?
    }
    catch (string e)
    {
        cout << "Error: " << e << endl;
    }
}

问题是-=操作员,旨在在右侧的指示位置擦除元素。当我保持在向量的边界范围内时,这是按预期工作的;但是,如果我指定了删除的界限,我不会得到 exception 。我得到了 seg fault 。我试图通过添加其他打印命令来确定SegFault发生的确切点:

void operator -= (const unsigned& b)
{
    cout << "In Overload!n";
    if (backpack.empty() || backpack.size() < b)
    {
        cout << "Exception!n";
        throw string("No such element exists.");
    }
    backpack.erase(backpack.begin() + b);
}

"异常!"线条永远不会达到。即使我应该对未定义的行为进行评估,该程序的故障才能达到这一点。我相信我缺少了解此过程如何工作的关键组成部分。有什么方法我应该写这个,以便可以扔掉而不是错?

在Linux X64架构上使用g++ -std=c++17 -Wall -Wextra -pedantic编译。

您的错误检查已关闭1。

if (backpack.empty() || backpack.size() < b)

如果std::vector背包仅包含两个值,则backpack.size()为2,而backpack将包含backpack[0]backpack[1]

不幸的是,如果索引b被AS 2传递,则此代码仍将尝试访问backpack[2],从而导致不确定的行为。

实际上,整个if语句可以简单地重写为:

if (b >= backpack.size())
    throw string("Out of Range");

您的代码中有一个错误。

考虑如果数组不为空,会发生什么,而代码中的b == backpack.size()会发生什么。

 if (backpack.empty() || backpack.size() < b)
            throw string("Out of Range");
 return backpack[b];

在这种情况下,backpack元素的有效索引是0backpack.size() - 1

如果b == backpack.size(),代码不会引发异常,并且将尝试返回backpack[backpack.size()],以提供未定义的行为。

不确定行为的一种可能症状是" segfault"。

避免问题的一种方法是将测试更改为backpack.size() <= b

另一种选择是利用std :: vector :: at(),它将在未结合的索引上抛出 std::out_of_range例外:

    T operator [] (const unsigned& b)
    {
        try 
        {
           return backpack.at(b);
        }
        catch (std::out_of_range& e)
        {
            throw string("Out of Range");
        }
    }
    void operator -= (const unsigned& b)
    {
        try
        {
            backpack.at(b);
            backpack.erase(backpack.begin() + b);
        }
        catch(std::out_of_range& e)
        {
           throw std::string("No such element exists.");
        }
    }

实时示例

最新更新