Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/153.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ std::向量分段故障而不是引发异常_C++_Vector_Exception Handling_Segmentation Fault - Fatal编程技术网

C++ std::向量分段故障而不是引发异常

C++ std::向量分段故障而不是引发异常,c++,vector,exception-handling,segmentation-fault,C++,Vector,Exception Handling,Segmentation Fault,我试图为std::vector创建一个容器类,让自己更多地了解模板、重载运算符和管理异常 目前,我只是定义基本操作。我有下面列出的模板类;我将+=和[]操作符重载为使用T推回向量,并分别直接访问向量的元素。这正如预期的那样有效 +=运算符执行它应该执行的操作,并且尝试对超出范围的元素使用[]运算符将按预期引发异常 以下是当前的原型类和实现: #include <iostream> #include <vector> #include <string> usi

我试图为
std::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!”行。程序在达到该点之前就会出现故障,即使我应该评估未定义的行为。我相信我在理解这个过程是如何工作的过程中缺少了一个关键的部分。有没有一种方法我应该写这篇文章,这样它可以抛出而不是错误


在Linux x64体系结构上使用
g++-std=c++17-Wall-Wextra-pedantic进行编译。

您的错误检查在1之前关闭

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

另一种选择是利用它将在越界索引上抛出
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.");
        }
    }

您的代码中存在“一次关闭”错误

考虑如果数组不是空的并且代码中的
b==backpack.size()
,会发生什么情况

 if (backpack.empty() || backpack.size() < b)
            throw string("Out of Range");
 return backpack[b];
if(backpack.empty()| | backpack.size()
在这种情况下,
backpack
元素的有效索引为
0
backpack.size()-1

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

未定义行为的一个可能症状是“segfault”


避免此问题的一种方法是将测试更改为
backpack.size(),为什么不直接使用
std::vector::at()
而不是为无效索引编写自己的测试?
vector::at()
保证抛出
超出范围的异常!“cout永远无法达到。程序在达到该点之前就出现故障”-您如何知道程序将达到该点?也许它去了叫背包。擦除
@PaulMcKenzie也许这是一个编码练习。真的。正如我提到的,我是自学C++的。因此,当我去学习一个新概念时,我倾向于尝试将新事物分解成块。首先,我专门为int编写了这段代码。然后我把它变成了一个模板。然后我添加了错误处理和异常抛出。接下来,我将使用标准异常,添加特性方法,等等。我发现这使我更容易掌握新信息,而不会不知所措。谢谢你的回复。我真的很感激!注意:要索引到容器中的正确数据类型是
size\u t
,而不是
unsigned int
(尽管在某些实现中它们可能是相同的)。除非这是为了学习,否则你可能不应该抓住这个例外。对于修复程序状态,您无法执行任何有意义的操作。它遇到了意外情况,唯一安全的选择是终止它。默认情况下,当您遇到未捕获的异常时会发生这种情况。非常感谢。看起来很棒!我真的很感谢你指出这一点。自学的一个问题是,很容易错过这样的小事情。:)的确这里的其他一些人已经指出了这个确切的问题。我已经改正了。我非常感谢您的反馈和帮助!有时,最简单的疏忽会使程序出错,不是吗?:)
    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.");
        }
    }
 if (backpack.empty() || backpack.size() < b)
            throw string("Out of Range");
 return backpack[b];