繁体   English   中英

使用二维向量时出现分割错误

[英]Segmentation fault while working with 2D vectors

我可以确切地知道为什么每当我开始遍历或将输入输入到二维向量时我的代码都会出现分段错误吗? 我不明白是什么导致了问题。

编辑: myvect[ans].push_back是造成问题的部分。

所以我的问题是为什么它不只是推回并在 myvect[ans] 位置创建一个向量? 这不是动态向量应该做的吗? 这是我的代码:

vector<vector<int>> myvect;
int ans = 2;

for(int i = 0; i < n; i++)
{
     myvect[ans].push_back(i+1);
     ans++;
}

for(int i = 0; i < myvect.size(); i++)
{
        if(!myvect[i].empty())
        {
            for(auto x: myvect[i])
                cout<<x<<" ";
        }
 }

在您的代码中,您正在索引向量,例如myvect[ans] ,但带有索引ans元素可能不存在,即myvect.size() <= ans ,C++ 默认不进行边界检查。 因此你有越界段错误。

C++被设计为超级高效和快速。 因此,在标准库的每个地方,如果程序员没有明确要求,C++ 不进行检查。

只有像 Python 或 JavaScript 这样的脚本语言会一直检查任何地方,但这使得它们有时比 C++ 慢 100-200 倍。

std::vector有一个索引的边界检查变体,您必须使用myvect.at(and) ,它与myvect[ans]相同,但如果索引超出范围则抛出异常。 但是不要忘记使用try-catch语法捕获异常。

但是.at()方法仍然不会自动调整数组大小以添加新元素。 为了拥有自动调整大小的功能,您必须在您的 vector 类版本中自己实现该功能。

接下来我编写了我的自动调整大小版本。 默认情况下,它还对[]运算符进行异常检查。 您可以使用任何自定义行为扩展标准 C++ 库中的任何类,就像我在下面为std::vector所做的那样。

下一个代码的输出:

Trying VectorT == "Vector<Vector<int, std::allocator<int> >, std::allocator<Vector<int, std::allocator<int> > > >"
    use_at == true
1 2 3 
Trying VectorT == "Vector<Vector<int, std::allocator<int> >, std::allocator<Vector<int, std::allocator<int> > > >"
    use_at == false
1 2 3 
Trying VectorT == "std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >"
    use_at == true
Exception: vector::_M_range_check: __n (which is 2) >= this->size() (which is 0)
Trying VectorT == "std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >"
    use_at == false
exited, segmentation fault

在线试试吧!

#include <vector>
#include <iostream>
#include <string>
#ifndef _MSC_VER
    // Only for Unix demangling
    #include <cxxabi.h>
#endif
using namespace std;

template < typename T, typename AllocatorT = typename std::vector<T>::allocator_type >
class Vector : public std::vector<T, AllocatorT> {
private:
    typedef std::vector<T, AllocatorT> SuperT;
    inline void FitSize(size_t i) {
        if (i > SuperT::size())
            SuperT::resize(i);
    }
public:
    template <typename ... Args>
    Vector(Args ... args) : SuperT(args ...) {}
    inline T & operator[] (size_t i) {
        FitSize(i + 1);
        return SuperT::operator[](i);
    }
    inline T const & operator[] (size_t i) const { return SuperT::at(i); }
    inline T & at(size_t i) {
        FitSize(i + 1);
        return SuperT::at(i);
    }
    inline T const & at(size_t i) const { return SuperT::at(i); }
};

// This function is just for informational purposes of demangling
char const * Demangle(char const * name) {
    #ifdef _MSC_VER
        return name;
    #else
        int status = 0;
        return abi::__cxa_demangle(name, 0, 0, &status);
    #endif
}

template <template < typename T, typename AllocatorT = typename std::vector<T>::allocator_type > class VectorT>
void Test(bool use_at) {
    try {
        VectorT< VectorT<int> > myvect;
        
        cout << "Trying VectorT == \"" << Demangle(typeid(myvect).name()) << "\"\n    use_at == " << (use_at ? "true" : "false") << endl;

        int ans = 2, n = 3;

        for(int i = 0; i < n; i++)
        {
            if (!use_at)
                myvect[ans].push_back(i+1);
            else
                myvect.at(ans).push_back(i+1);
            ans++;
        }

        for(int i = 0; i < myvect.size(); i++)
        {
            if(!myvect[i].empty())
            {
                for(auto x: myvect[i])
                    cout << x << " ";
            }
        }
        cout << endl;
    } catch (exception const & ex) {
        cerr << "Exception: " << ex.what() << endl;
    } catch (...) {
        cerr << "Unknown Exception!" << endl;
    }
}

int main() {
    Test<Vector>(true);
    Test<Vector>(false);
    Test<vector>(true);
    Test<vector>(false);
    return 0;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM