xutility在使用自定义向量返回isstream时读取访问冲突

时间:2018-02-26 14:43:21

标签: c++ c++11 visual-c++ vector c++14

所以我有一个定制的矢量类,还有一个自定义分配器:

#define _SCL_SECURE_NO_WARNINGS

#include <iostream>
#include <exception>
#include <sstream>
#include <string>
#include <iostream>

namespace mem {
    template<typename T>
    class allocator {
    public:
        //
        T * allocate(int n);                    //allocate space for n objects of type T
        void deallocate(T* p);      //deallocate n objects of type T starting at p

        void construct(T* p, const T& v);   // construct a T with the value v in p
        void destroy(T* p);                 // destroy the T in p
    };

    template<typename T> T* allocator<T>::allocate(int n)                   //allocate space for n objects of type T
    {
        T* res = (T*)malloc(sizeof(T)*n);
        if (res == nullptr)
            throw std::bad_alloc();

        return res;
    }

    template<typename T> void allocator<T>::deallocate(T* p/*, int n*/)     //deallocate n objects of type T starting at p
    {
        free(p);
    }

    template<typename T> void allocator<T>::construct(T* p, const T& v)                 // construct a T with the value v in p
    {
        new(p) T(v);
    }

    template<typename T> void allocator<T>::destroy(T* p)                   // destroy the T in p
    {
        p->~T();
    }
}

namespace vec {
    template<typename T, typename A = mem::allocator<T>>
    class vector {
        A alloc;        //use allocate to handle memory for elements
        int sz;         //the size
        T* elem;        //a pointer to the elements
        int space;      //size + free space
    public:
        using size_type = unsigned long;
        using value_type = T;
        using iterator = T * ;
        using const_iterator = const T*;

        vector() :sz{ 0 }, elem{ nullptr }, space{ 0 } {}
        explicit vector(int s) :sz{ s }, elem{ new T[s] }, space{ s }
        {
            for (int i = 0; i < sz; ++i) elem[i] = 0;           // elements are initalized
        }

        vector(const vector& arg);                              //copy constructor
        vector& operator =(const vector& a);                    //copy assignment

        vector(vector&& a);                                     //move constructor
        vector& operator=(vector&& a);                          //move assignment

        ~vector() { delete[] elem; }                            //destructor

        void reserve(int newalloc);
        void resize(int newsize, T val = T());                              //growth
        void push_back(const T& val);

        iterator begin() { return elem; }
        const_iterator begin()const { return elem; }
        iterator end() { return elem + sz; }
        const_iterator end() const { return elem + sz; }
        size_type size() { return sz; }

        iterator back() { return end() - 1; }
        const_iterator back() const { return end() - 1; }

    };

    template<typename T, typename A> vector<T, A>::vector(const vector<T, A>& a)                    //copy constructor
        :sz{ a.sz }, elem{ new T[a.sz] }
    {
        copy(a.elem, a.elem + sz, elem);
    }

    template<typename T, typename A> vector<T, A>& vector<T, A>::operator =(const vector<T, A>& a)  //copy assignment
    {
        if (this == &a) return *this;           //return if self assignment

        if (a.sz <= space) {                    //enough space no need for new allocation
            for (int i = 0; i < a.sz; ++i)      //copy elements
                alloc.construct(&elem[i], a.elem[i]);
            sz = a.sz;
            return *this;
        }

        T* p = alloc.allocate(a.sz);//allocate new size
        for (int i = 0; i < a.sz; ++i)  //copy elements
            alloc.construct(&p[i], a.elem[i]);
        for (int i = 0; i < sz; ++i)
            alloc.destroy(&elem[i]);            //destroy
        alloc.deallocate(elem);
        space = sz = a.sz;              //set new size
        elem = p;                       //set new elements
        return *this;                   //return a self reference
    }

    template<typename T, typename A> vector<T, A>::vector(vector<T, A>&& a)     //move constructor
        :sz{ a.sz }, elem{ a.elem }
    {
        a.sz = 0;                           //make a the empty vector
        a.elem = nullptr;
    }

    template<typename T, typename A> vector<T, A>& vector<T, A>::operator=(vector<T, A>&& a)            //move assignment
    {
        delete[] elem;                  //deallocate old space
        elem = a.elem;                  //copy a's elem and sz
        sz = a.sz;
        a.elem = nullptr;               //make a the empty vector
        a.sz = 0;
        return *this;
    }

    template<typename T, typename A> void vector<T, A>::reserve(int newalloc)
    {
        if (newalloc <= space) return;      //never decrease allocation
        T* p = alloc.allocate(newalloc);        //alocate new space
        for (int i = 0; i < sz; ++i)
            alloc.construct(&p[i], elem[i]);    //copy
        for (int i = 0; i < sz; ++i)
            alloc.destroy(&elem[i]);            //destroy
        alloc.deallocate(elem/*, space*/);          //deallocate old space
        elem = p;
        space = newalloc;
    }

    template<typename T, typename A> void vector<T, A>::push_back(const T& val)
    {
        if (space == 0)
            reserve(8);
        else if (space == sz)
            reserve(2 * space);
        alloc.construct(&elem[sz], val);    //add val at the end
        ++sz;
    }

    template<typename T, typename A> void vector<T, A>::resize(int newsize, T val)
    {
        reserve(newsize);
        for (int i = sz; i < newsize; ++i)
            alloc.construct(&elem[i], val);     //construct
        for (int i = newsize; i < sz; ++i)
            alloc.destroy(&elem[i]);            //destroy
        sz = newsize;
    }

    template<typename T, typename A> std::ostream& operator<<(std::ostream& os, const vector<T, A>& obj) //requires Element<T> && Allocator<A>
    {
        for (const auto& x : obj)
            os << x << ' ';
        os << '\n';
        return os;
    }

    template<typename T, typename A> std::istream& operator>>(std::istream& is, vector<T, A>& obj)
    {
        std::string line;
        std::getline(is, line);
        if (is.bad() || is.fail())
            return is;

        std::istringstream istr{ line };
        vector<T, A> tmp;

        while (true) {
            T tmp_in = T();
            istr >> tmp_in;
            if (istr.fail()) {
                istr.clear();
                std::string invalid;
                istr >> invalid;
                continue;
            }
            tmp.push_back(tmp_in);
            if (istr.eof())break;
        }

        for (const auto& x : tmp)
            obj.push_back(x);
        return is;                      //its sends me to xutility in this step
    }
}


int main()
{
    //vec::vector <int> test;       //input "1 2 3 4 5" works fine with cin >>test
    vec::vector <std::string> test;  //input "this is a test"  breaks into xutility

    while (true) {
        std::cin >> test;           //breaks into xutility
        std::cout << test << '\n';
    }
}

现在出现以下问题。如果向量是向量,我可以读取向量值。因此添加1 2 3 4 5是没有问题的。 矢量工作正常。 如果我将容器类型更改为vector并通过cin&gt;&gt;读入“hello this is a test”测试;我在xutility.h中得到了一个小问题:

        // MEMBER FUNCTIONS FOR _Container_base12
inline void _Container_base12::_Orphan_all() _NOEXCEPT
    {   // orphan all iterators
 #if _ITERATOR_DEBUG_LEVEL == 2
    if (_Myproxy != 0)               //It points on this line
        {   // proxy allocated, drain it
        _Lockit _Lock(_LOCK_DEBUG);

        for (_Iterator_base12 **_Pnext = &_Myproxy->_Myfirstiter;
            *_Pnext != 0; *_Pnext = (*_Pnext)->_Mynextiter)
            (*_Pnext)->_Myproxy = 0;
        _Myproxy->_Myfirstiter = 0;
        }
 #endif /* _ITERATOR_DEBUG_LEVEL == 2 */
    }

Visual Studio 2017抛出: 抛出异常:读取访问冲突。这是0xC83FB858。

如何调用此标头以及它的含义是什么? 我真的不知道最新情况。

我用std :: vector替换了自定义向量,然后它也可以工作。

编辑:我稍微最小化了代码并为向量添加了命名空间。仍然是同样的行为:

vec::vector<int> test;
std::cin >> test;       //Ok: Example input 1 2 3 4 5

vec::vector<std::string> test;
std::cin >> test;       //Mem access violation in xutility: Example input "this is a test"

0 个答案:

没有答案