So i have a custom made vector class with also an custom allocator:
alloc.h:
#ifndef ALLOC1234_GUARD
#define ALLOC1234_GUARD
namespace mem {
template<typename T>
class allocator {
public:
//
T* allocate(int n); //allocate space for n objects of type T
void deallocate(T* p/*, int n*/); //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();
}
}
#endif
vector.h:
#ifndef VECTOR1234_GUARD
#define VECTOR1234_GUARD
#include "alloc.h"
#include <exception>
#include <sstream>
#include <string>
#include <iostream>
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
T& at(int n) { //checked access;
if (n < 0 || sz <= n)
throw std::out_of_range("vector");
return elem[n];
};
const T& at(int n) const{
if (n < 0 || sz <= n)
throw std::out_of_range("vector");
return elem[n];
};
T& operator[](int n) { return elem[n]; } //access: return reference
const T& operator[] (int n) const { return elem[n]; }
int size() const { return sz; } //the current size
int capacity() const { return space; }
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; }
iterator insert(iterator p, const T&val);
iterator erase(iterator p);
};
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> //requires Element<T> && Allocator<A>
typename vector<T, A>::iterator vector<T, A>::erase(iterator p)
{
if (p == end()) return p;
for (auto pos = p + 1; pos != end(); ++pos)
*(pos - 1) = *pos; //copy element "one position to the left
alloc.destroy(&*(end() - 1)); //destroy surplus copy of last element
--sz;
return p;
}
template<typename T, typename A> //requires Element<T> && Allocator<A>
typename vector<T, A>::iterator vector<T, A>::insert(iterator p, const T&val)
{
int index = p - begin();
if (size() == capacity())
reserve(size() == 0 ? 8 : 2 * size()); //make sure we have space
//first copy last element in uninitalized space:
alloc.construct(elem + sz, *back());
++sz;
iterator pp = begin() + index; //the place to put val
for (auto pos = end() - 1; pos != pp; --pos)
*pos = *(pos - 1); //copy elements one position to the right;
*(begin() + index) = val; //insert val;
return pp;
}
template<typename T, typename A> //requires Element<T> && Allocator<A>
std::ostream& operator<<(std::ostream& os, const vector<T,A>& obj)
{
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; // it sends me to xutility.h here
}
#endif
main.cpp:
#define _SCL_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
#include <exception>
#include "vector.h"
using namespace std;
inline void keep_window_open(string s)
{
if (s == "") return;
cin.clear();
cin.ignore(120, '\n');
for (;;) {
cout << "Please enter " << s << " to exit\n";
string ss;
while (cin >> ss && ss != s)
cout << "Please enter " << s << " to exit\n";
return;
}
}
int main()
try {
//vector <int>test; //this works fine
vector <string> test;
while (true) {
cin >> test;
cout << test << '\n';
}
keep_window_open("~");
}
catch (runtime_error& e) {
cerr << e.what() << "\n";
keep_window_open("~");
}
catch (out_of_range& e) {
cerr << "out of range access " << e.what() << "\n";
keep_window_open("~");
}
catch (bad_alloc& e) {
cerr <<"memory alloc failed "<< e.what() << "\n";
keep_window_open("~");
}
catch (...) {
cerr << "unknown error " << "\n";
keep_window_open("~");
}
Now the following problem. I can read in vector values if the vector is vector. So adding 1 2 3 4 5 is no problem. Also vector works fine. If i change the container type to vector and read in "hello this is a test" via cin >> test; I get a crahs in 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 throws: Exception thrown: read access violation.this was 0xC83FB858.
How can this header even get called and what is the meaning of it? I really have no idea whats going on.
I replaced the custom vector with std::vector and then it works.