Runtime error while implementing vector in c++ - c++

I am trying to implement my own version of vector in c++.
So far I have done this..
#include<iostream>
#include<string>
using namespace std;
template<class T>
class vec
{
public:
T *a;
int i,N;
vec(int N=0):N(N)
{
i=-1;
a=(T *)malloc(N*sizeof(T));
}
void push_back(const T& t);
T at(const int& index) const;
};
template<class T>
void vec<T>::push_back(const T& t)
{
if(++i==N)
{
a=(T *)realloc(a,(++N)*sizeof(T));
}
a[i]=t;
}
template<class T>
T vec<T>::at(const int& index) const
{
return a[index];
}
int main()
{
vec<string> v;
v.push_back("2");
v.push_back("1");
v.push_back("3");
cout<<v.at(0)<<endl;
return 0;
}
But I am getting a run time error when I run this
Where is the error in the above code?
I am using c++ and visual studio to run.

In this case you need to use placement new.
something like this:
// Allocate memory
void* mem = malloc(sizeof(std::string));
// Call constructor via placement new on already allocated memory
std::string* ptr = new (mem) std::string();
But then, you are forced to explicitly call destructor for this memory
ptr->~std::string();
Overall - this is not really good way to achieve what you want. It's more convenient to use usual new\delete operators and copy internal data on re-allocation (how it was done in STL vector)

Related

Can I force std::vector to leave a memory leak?

Can I force std::vector to not deallocate its memory after the vector goes out of scope?
For example, if I have
int* foo() {
std::vector<int> v(10,1); // trivial vector
return &v[0];
}
int main()
{
int* bar = foo();
std::cout << bar[5] << std::endl;
}
There is no guarantee that the values will still be accessible here.
I am currently simply doing this
int* foo() {
std::vector<int> v(10,1);
int* w = new int[10];
for (int i=0; i<10; i++) {
w[i] = v[i];
}
return w;
}
but it is a little wasteful to repopulate a whole new array. Is there a way to force std::vector to not delete its array?
Note: I am not returning the vector itself because I am interfacing c++ with python using SWIG, and ARG_OUTVIEW_ARRAY requires a raw pointer and, in fact, an intentional memory leak. I would still however like to be able to make use of vector features while constructing the data itself.
It is possible but you should never do it. Forcing a vector to leave memory leak is a terrible idea and if you need such a thing then you need to re-think your design. std::vector is a resource managing type whose one of the main goals is to ensure that we don't have a leak. Never try to break that.
Now, to answer your specific question: std::vector takes an allocator type as second template parameter which is default to std::allocator<T>. Now you can write a custom allocator that doesn't release any memory and use that with your vector. Writing a custom allocator is not very trivial work, so I'm not going to describe that here (but you can Google to find the tutorials).
If you really want to use custom allocator then you must ensure that your vector never triggers a grow operation. Cause during growing capacity the vector will move/copy data to new location and release the old memories using the allocator. If you use an allocator that leaks then during growing you not only retain the final data, but also retain the old memories which I'm sure that you don't want to retain. So make sure that you create the vector with full capacity.
The vector is desiged to prevent leaks.
But if you want to shoot yourself in the foot, it's possible. Here's how you prevent the vector from deallocating its internal array:
int *foo()
{
std::vector<int> v(10,1);
int *ret = v.data();
new (&v) std::vector<int>; // Replace `v` with an empty vector. Old storage is leaked.
return ret;
}
As the other answers say, you should never do it.
No.
Vectors are not implemented to have memory leaks, and the interface does not provide a way to create one.
You can't "steal" the memory (removing ownership of it from the vector), which is possibly a bit of a shame.
Sorry, but you are going to have to either copy (as you're doing now), or not use vector.
This is a bad idea, but possible by creating a custom allocator that does not deallocate as said in other answers.
For example : (boilerplate mostly from cppref)
#include <cstdlib>
#include <new>
#include <vector>
template <typename T>
struct LeakingAllocator
{
using value_type = T;
LeakingAllocator() = default;
template <typename U> constexpr LeakingAllocator(const LeakingAllocator<U>&) noexcept {}
T* allocate(std::size_t n)
{
if(n > std::size_t(-1) / sizeof(T)) throw std::bad_alloc(); // check for overflow
if(auto p = static_cast<T*>(std::malloc(n*sizeof(T)))) return p; // return p if malloc returns a valid object
throw std::bad_alloc(); // otherwise just throw.
}
void deallocate(T* p, std::size_t) noexcept { /*leak intentionally*/ }
};
template <typename T, typename U>
bool operator==(const LeakingAllocator<T>&, const LeakingAllocator<U>&) { return true; }
template <typename T, typename U>
bool operator!=(const LeakingAllocator<T>&, const LeakingAllocator<U>&) { return false; }
template <typename T>
using LeakingVector = std::vector<T, LeakingAllocator<T>>;
Then code like
int* ret()
{
LeakingVector<int> a;
a.resize(10);
return &a[0];
}
int main()
{
auto ptr = ret();
*ptr = 10;
std::cout << *ptr;
}
becomes valid.
Not sure but, yes.
You can create a custum allocator who do nothing when deallocate => leak
Or may be you can jsut create your vectoron the heap so it will leak anyway.
int* foo() {
std::vector<int>* v = new std::vector<int>(10,1);
return &((*v)[0]);
// no delete
}
int main()
{
int* bar = foo();
std::cout << bar[5] << std::endl;
}
No.
And you're doing it wrong. Return the vector instead so the lifetime works out:
Write your own special Python memory vector class, something like (most crudely):
template <typename T>
class python_vector
{
T* buffer_;
public:
python_vector(size_t n, const T& value) : buffer_{new T(n)}
{}
// copy, assignment, operator[](), *etc*
~python_vector()
{
// DO NOTHING!
}
}
python_vector<int> foo() {
python_vector<int> v(10,1);
// process v
return v;
}
int main()
{
python_vector<int> bar = foo(); // copy allusion will build only one python_vector here
std::cout << bar[5] << std::endl;
}
In C++ you would most probably write:
auto foo()
{
std::vector<int> v(10,1); // trivial vector
return v;
}
int main()
{
const auto bar = foo();
std::cout << bar[5] << std::endl;
}

build success but run fail for Stack class

So, I am trying to run the class below with
int x = 5;
mystack<int> st;
st.push(x);
However, I keep getting build failure, I can't seem to figure out why.
#ifndef MYSTACK_H
#define MYSTACK_H
#include <vector>
using namespace std;
template<typename T>
class mystack {
private:
vector<T> data;
int size = 0;
public:
void push(T const &);
};
template<typename T>
void mystack<T>::push(T const & elem) {
data[size] = elem;
size++;
}
RUN FAILED ( exit value -1, 073, 741, 819, total time: 1s)
Also completely separate question, how do I throw an underflow? I tried
throw underflow_error();
Initially your vector<T> data is empty. Its size() is 0. You cannot access to any of its elements. That might be the reason of getting an error.
Try using this code:
template<typename T>
void mystack<T>::push(T const & elem) {
data.push_back(elem);
}
It actually will increase you data.size() by 1 every time you push an element.
Don't want to use any vector STL
Wonder you are having vector<T> in code, looks like STL. You can use plain dynamic arrays as an alternative or even static ones.
template<typename T>
class mystack {
private:
T* data;
int size = 0;
int maxSize;
public:
mystack(int maxSize) :maxSize(maxSize) { data = new data[maxSize]; }
~mystack() { delete[] data; }
void push(T const &);
};
template<typename T>
void mystack<T>::push(T const & elem) {
// here you may check if you already reached the maxSize;
data[size++] = elem;
}
Note that in order to fully simulate STL vector behaviour you should consider reallocating the array each time you have size = allocateSize. STL vector makes this every time the number of elements hits the power of 2, it doubles its size.
I propose you to use std::stack instead of implement your own stack using std::vector. If you don't want use STL at all, your should control memory allocation and deletion by yourself. In your example, in the line data[size] = elem;, you assign value to not allocated memory, it is your problem. You can fix it that way, if you don't want to use push_back() method:
template<typename T>
void mystack<T>::push(T const & elem) {
size += 1;
data.resize(size);
data[size] = elem;
}
About std::underflow_error. It designed for arithmetic underflow errors. Anyway, this class has constructor where your should put string, so you need change throw underflow_error(); to throw underflow_error("Error message");.

Using unique_ptr with gsl_vector

One of my favorite aspects of unique_ptr is the automatic memory management it provides. I would like to use unique_ptr with something like a GSL vector.
However, gsl_vector has its own mechanism for freeing memory (gsl_vector_free). Is there a way to force the unique pointer to use GSL's vector freeing method? Valgrind (correctly) reports a mismatched use of malloc/delete when creating a unique_ptr<gsl_vector> below:
#include <memory>
#include <gsl/gsl_vector.h>
void mem_gsl() {
gsl_vector *vec;
vec = gsl_vector_calloc(2);
gsl_vector_set(vec, 0, 2.0);
printf("%f\n", gsl_vector_get(vec, 0));
gsl_vector_free(vec); // Without this, there is a memory leak.
}
void mem_unique_ptr() {
std::unique_ptr<gsl_vector> vec;
vec.reset(gsl_vector_calloc(2));
// Using .get() each time I want to use the gsl_vector seems like overhead.
gsl_vector_set(vec.get(), 0, 2.0);
printf("%f\n", gsl_vector_get(vec.get(), 0));
// Valgrind correctly reports a mismatched use of delete and free.
}
int main(int argc, char *argv[]) {
mem_gsl();
mem_unique_ptr();
return 0;
}
Additionally, having to call get() each time I want to access a vector element seems rather tedious. Is there a way around this?
You can do it by providing std::unique_ptr with a custom deleter. Something like this would probably do:
auto del = [](gsl_vector* p) { gsl_vector_free(p); };
std::unique_ptr<gsl_vector, decltype(del)> vec(gsl_vector_calloc(2), del);
Having a make_unique_gsl_vector amd a custom deleter:
#include <memory>
// Fake gsl
typedef int gsl_vector;
gsl_vector* gsl_vector_calloc(std::size_t) { return 0; }
void gsl_vector_free(gsl_vector*) {}
// Deleter
struct gsl_vector_deleter {
void operator () (gsl_vector* p) {
gsl_vector_free(p);
}
};
// Unique Pointer
typedef std::unique_ptr<gsl_vector, gsl_vector_deleter> unique_gsl_vector;
unique_gsl_vector make_unique_gsl_vector() {
return unique_gsl_vector(gsl_vector_calloc(2));
}
int main() {
make_unique_gsl_vector();
return 0;
}
To avoid the .get() calls and other boilerplate associated with wrapping a gsl_vector in a unique_ptr, you could create a small RAII wrapper.
namespace gsl {
class vector
{
std::unique_ptr<gsl_vector, decltype(&gsl_vector_free)> v_;
public:
explicit vector(std::size_t num)
: v_(gsl_vector_calloc(num), gsl_vector_free)
{}
double operator[](std::size_t idx) const
{
return gsl_vector_get(v_.get(), idx);
}
void set(std::size_t idx, double value)
{
gsl_vector_set(v_.get(), idx, value);
}
};
}
This not only avoids boilerplate, but also allows you to easily extend functionality, say for instance, adding a constructor that takes a std::initializer_list<double> so you can construct and initialize the vector in a single expression.
Live example

Initialising nested templates

I'm trying to learn more about templates and have come across a problem I can't seem to solve. At the moment the class below works fine.
#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
template <class T, int s>
class myArray{
public:
T* data;
inline T& operator[](const int i){return data[i];}
myArray(){
data=new T[s];
}
myArray(const myArray& other){
data=new T[s];
copy(other.data,other.data+s,data);
}
myArray& operator=(const myArray& other){
data=new T[s];
copy(other.data,other.data+s,data);
return *this;
}
~myArray(){delete [] data;}
};
If I use it:
myArray<myArray<myArray<int,10>,20>,30> a;
a is now 30x20x10 array that I can access with the normal array brackets e.g. a[5][5][5]. I wish to add a feature so that I could write:
myArray<myArray<myArray<int,10>,20>,30> a(10);
and initialise all of the entries to 10 for example. I can't work out how to do this. As I understand, each layer of myArray is constructed using the default constructor. If I changed this to something like:
myArray(int n=0){
data=new T[s];
fill(data,data+s,n); //T might not be of type int so this could fail.
}
I think this should fail when data is not of type int (i.e. on any array on dimensions > 1), however it doesn't. It works when the array is square, but if not then some of the entries aren't set to 10. Does anyone have an idea how the standard vectors class achieves this? Any help would be amazing. Thanks!
Well, try something like this:
myArray()
: data(new T[s]()) // value-initialization!
{
}
myArray(T const & val)
: data(new T[s]) // default-initialization suffices
{
std::fill(data, data + s, val);
}
If you're into variadic templates, you might cook up something even more grotesque involving variadically filled initializer lists, but I think we've done enough learning for one week.
Note the fundamental flaw in using new: Either version requires that your class T can be instantiated in some "default" state, and that it be assignable, even though we never require the default state in the second version. That's why "real" libraries separate memory allocation and object construction, and you never see a new expression unless its the placement version.
std::vector uses placement new on memory blocks. It constructs the data.after allocating the memory in a second line of code.
This technique would work for you as well. Be careful with placement new as it requires you to call destructors manually as well.
Here is a half-assed route without placement new:
template<typename U>
explicit MyArray( U const& constructFromAnythingElse )
{
AllocateSpace(N); // write this, just allocates space
for (int i = 0; i < N; ++i)
{
Element(i) = T( constructFromAnythingElse );
}
}
with placement new, you have to allocate the memory first, then construct in-place, and then remember to destroy each element at the end.
The above is half-assed compared to a placement new route, because we first construct each element, then build another one, and use operator= to overwrite it.
By making it a template constructor on an arbitrary type, we don't rely on multiple conversion to get multiple levels down into the array. The naive version (where you take a T const&) doesn't work because to construct an array of arrays of arrays of T, the outermost one expects an array of arrays of T as an argument, which expects an array of T as an argument, which expects a T -- there are too many levels of user defined construction going on there.
With the above template constructor, the array of array of array of T accepts any type as a constructor. As does the array of array of T, as does the array of T. Finally, the T is passed in whatever you constructed the outermost array of array of array of T, and if it doesn't like it, you get a compiler error message that is nearly completely unreadable.
Make specialization for arrays containing other arrays. To do this you need some common implementation class to be used in general and specialized MyArray:
Common implementation (I made some fixes for you - see !!! comments):
template <class T, int s>
class myArrayImpl {
public:
T* data;
T& operator[](int i){return data[i];} //!!! const before int not needed
const T& operator[](int i) const {return data[i];} //!!! was missing
myArrayImpl(){
data=new T[s]();
}
myArrayImpl(const myArrayImpl & other){
data=new T[s];
copy(other.data,other.data+s,data);
}
myArrayImpl& operator=(const myArrayImpl& other){
T* olddata = data; // !!! need to store old data
data=new T[s];
copy(other.data,other.data+s,data);
delete [] olddata; //!!! to delete it after copying
return *this;
}
~myArrayImpl(){delete [] data;}
};
Then make general implementation - note the definition of value_type and setAll:
template <class T, int s>
class myArray : private myArrayImpl<T,s> {
typedef myArrayImpl<T,s> Impl;
public:
using Impl::operator[];
myArray() : Impl() {}
typedef T value_type; // !!!
explicit myArray(const value_type& value) {
setAll(value);
}
void setAll(const value_type& value) {
fill(this->data, this->data + s, value);
}
};
And the specialized version for myArray of myArray - see also differences in value_type and setAll:
template <class T, int s1, int s2>
class myArray<myArray<T,s2>,s1> : private myArrayImpl<myArray<T,s2>,s1> {
typedef myArrayImpl<myArray<T,s2>,s1> Impl;
public:
using Impl::operator[];
myArray() : Impl() {}
typedef typename myArray<T,s2>::value_type value_type; // !!!
explicit myArray(const value_type& value) {
setAll(value);
}
void setAll(const value_type& value) {
for_each(this->data, this->data + s1, [value](myArray<T,s2>& v) { v.setAll(value); });
}
};
And usage:
int main() {
myArray<myArray<myArray<int,7>,8>,9> a(7);
std::cout << a[0][0][0] << std::endl;
std::cout << a[8][7][6] << std::endl;
}
Full example here: http://ideone.com/0wdT9D

Overloaded [] operator on template class in C++ with const / nonconst versions

Whew, that was a long title.
Here's my problem. I've got a template class in C++ and I'm overloading the [] operator. I have both a const and a non-const version, with the non-const version returning by reference so that items in the class can be changed as so:
myobject[1] = myvalue;
This all works until I use a boolean as the template parameter. Here's a full example that shows the error:
#include <string>
#include <vector>
using namespace std;
template <class T>
class MyClass
{
private:
vector<T> _items;
public:
void add(T item)
{
_items.push_back(item);
}
const T operator[](int idx) const
{
return _items[idx];
}
T& operator[](int idx)
{
return _items[idx];
}
};
int main(int argc, char** argv)
{
MyClass<string> Test1; // Works
Test1.add("hi");
Test1.add("how are");
Test1[1] = "you?";
MyClass<int> Test2; // Also works
Test2.add(1);
Test2.add(2);
Test2[1] = 3;
MyClass<bool> Test3; // Works up until...
Test3.add(true);
Test3.add(true);
Test3[1] = false; // ...this point. :(
return 0;
}
The error is a compiler error and the message is:
error: invalid initialization of non-const reference of type ‘bool&’ from a temporary of type ‘std::_Bit_reference’
I've read up and found that STL uses some temporary data types, but I don't understand why it works with everything except a bool.
Any help on this would be appreciated.
Because vector<bool> is specialized in STL, and does not actually meet the requirements of a standard container.
Herb Sutter talks about it more in a GOTW article: http://www.gotw.ca/gotw/050.htm
A vector<bool> is not a real container. Your code is effectively trying to return a reference to a single bit, which is not allowed. If you change your container to a deque, I believe you'll get the behavior you expect.
A vector<bool> is not implemented like all other vectors, and does not work like them either. You are better off simply not using it, and not worrying if your code can't handle its many peculiarities - it is mostly considered to be A Bad Thing, foisted on us by some unthinking C++ Standard committee members.
Some monor changes to your class should fix it.
template <class T>
class MyClass
{
private:
vector<T> _items;
public:
// This works better if you pass by const reference.
// This allows the compiler to form temorary objects and pass them to the method.
void add(T const& item)
{
_items.push_back(item);
}
// For the const version of operator[] you were returning by value.
// Normally I would have returned by const ref.
// In normal situations the result of operator[] is T& or T const&
// But in the case of vector<bool> it is special
// (because apparently we want to pack a bool vector)
// But technically the return type from vector is `reference` (not T&)
// so it you use that it should compensate for the odd behavior of vector<bool>
// Of course const version is `const_reference`
typename vector<T>::const_reference operator[](int idx) const
{
return _items[idx];
}
typename vector<T>::reference operator[](int idx)
{
return _items[idx];
}
};
As the other answers point out, a specialization is provided to optimize for space allocation in the case of vector< bool>.
However you can still make your code valid if you make use of vector::reference instead of T&. In fact it is a good practice to use container::reference when referencing data held by a STL container.
T& operator[](int idx)
becomes
typename vector<T>::reference operator[](int idx)
Of course ther is also a typedef for const reference:
const T operator[](int idx) const
and this one becomes (removing the useless extra copy)
typename vector<T>::const_reference operator[](int idx) const
The reason for the error is that vector<bool> is specialized to pack the boolean values stored within and vector<bool>::operator[] returns some sort of proxy that lets you access the value.
I don't think a solution would be to return the same type as vector<bool>::operator[] because then you'd be just copying over the regrettable special behavior to your container.
If you want to keep using vector as the underlying type, I believe the bool problem could be patched up by using a vector<MyBool> instead when MyClass is instantiated with bool.
It might look like this:
#include <string>
#include <vector>
using namespace std;
namespace detail
{
struct FixForBool
{
bool value;
FixForBool(bool b): value(b) {}
operator bool&() { return value; }
operator const bool& () const { return value; }
};
template <class T>
struct FixForValueTypeSelection
{
typedef T type;
};
template <>
struct FixForValueTypeSelection<bool>
{
typedef FixForBool type;
};
}
template <class T>
class MyClass
{
private:
vector<typename detail::FixForValueTypeSelection<T>::type> _items;
public:
void add(T item)
{
_items.push_back(item);
}
const T operator[](int idx) const
{
return _items[idx];
}
T& operator[](int idx)
{
return _items[idx];
}
};
int main(int argc, char** argv)
{
MyClass<string> Test1; // Works
Test1.add("hi");
Test1.add("how are");
Test1[1] = "you?";
MyClass<int> Test2; // Also works
Test2.add(1);
Test2.add(2);
Test2[1] = 3;
MyClass<bool> Test3; // Works up until...
Test3.add(true);
Test3.add(true);
Test3[1] = false; // ...this point. :(
return 0;
}