dynamic arrays and operator overloading cause memory crash - c++

To illustrate my problem I minimalize my source:
#include <iostream>
class vec{
public:
float* X;
int DIM;
vec(int dimension)
{
DIM = dimension;
X = new float[dimension];
for (int i=0;i<DIM;i++)
X[i] = (float) rand()/RAND_MAX;
}
~vec(void){
delete [] X;
}
vec operator-( vec const& rhs )
{
vec ans(DIM);
for (int i=0;i<DIM;i++)
ans.X[i] = X[i] - rhs.X[i];
return ans;
}
};
int main(){
vec A(5),B(5),C(5);
C= A-B;
return 0;
}
When I execute this program I get an error that a heap was destroyed. I am pretty sure that the destructor is my problem. In the line with C= A-B; the variable ans will be destroyed by the constructor and cannot be returned. Is that right?
If I delete the line delete [] X; everything is ok. But it won't free up the memory.
I did my homework and consult one of the most famous search engine for this problem but didn't find any answer. How can I fix it?

C = A-B calls the default copy-assignment operator (as you haven't defined one). Therefore two different objects will point to the same dynamically-allocated array.
You need to read up on the Rule of Three (in a nutshell: if you define any of the destructor, the copy constructor or the copy-assignment operator, you probably need to define them all).
But preferably, you should avoid using raw arrays entirely; use a container type that manages its own memory.

Related

C++ my copy constructor fails to move the memory to a new area

So I've recently started to work on getting my own vector class working and I'm a little bit stuck on my copy constructor. I'm obviously rather new to c++ and was hoping the good guys at stack overflow could help me out a bit. So I got this copy constructor which copies the actual ptr being used, the end index of the ptr (the elements the user can use) and the actual capacity/reserved memory the ptr has, plus the size of the used memory.
vector(const vector &other) : storage(other.storage), capacity(other.capacity),
endIndex(other.endIndex), m_size(other.m_size)
{
T* storage = new T[capacity];
memcpy(storage, other.storage, sizeof(T) * capacity);
}
The issue is that while it seemingly copies the information successfully, if one of the objects run out of scope, the information, or at least some of it gets deleted. If I also do a push_back on one of the vector objects, it happens on both of them. So it's fairly safe to say that they share address for their ptr. For example if I run this code in my main function
int main()
{
vector<int> vec;
vec.push_back(5);
vec.push_back(55);
vec.push_back(500);
vector<int> vec1 = vec;
for (int i = 0; i < vec1.size(); i++)
{
std::cout << vec1[i] << std::endl;
}
return 0;
}
I will get this error message
5
55
500
free(): double free detected in tcache 2
Aborted (core dumped)
I'm assuming this is because the ptr gets deleted while going through the loop and it in turn crashes the program in a nice fashion. Another example of the push_back is
int main()
{
vector<int> vec;
vec.push_back(5);
vec.push_back(55);
vec.push_back(500);
vector<int> vec1 = vec;
vec.push_back(55);
for (int i = 0; i < vec1.size() + 1; i++)
{
std::cout << vec1[i] << std::endl;
}
return 0;
}
Where you can obviously see that i actually push_back on the original vector object and not the new one, i even have to increase the for-loops scope to be able to see the object on the new vector, hinting at the size integer in the new object is unchanged from before. Output of this code is:
5
55
500
55
free(): double free detected in tcache 2
Aborted (core dumped)
I don't expect anyone to take time out of their day to debug my code, I don't want that. I'm merely asking for a pair of professional eyes to glance over it and help a newbie out. Thanks in advance.
There are multiple issues with your code.
The first and foremost one is this:
T* storage = new T[capacity];
That storage is not the same as the member variable storage. It is a local variable that just happens to have the same name. Once the copy constructor is complete, you haven't done anything except leak memory.
In addition, you have this:
vector(const vector &other) : storage(other.storage),
This assigns the pointer other.storage to this. This is actually where the double-free comes from. You are doing a shallow copy, thus when this and other are destroyed, the same pointer value will be used in the call to delete [] in the destructor.
The third issue is this:
memcpy(storage, other.storage, sizeof(T) * capacity);
This will not work for types that are not trivially-copyable. Let's say you fix all the issues except this one. This code will fail miserably:
vector<std::string> s;
and the reason is that you can't use memcpy to copy std::string objects, since std::string is not trivially-copyable.
The fix is to use std::copy, not memcpy, since std::copy is (should be) smart enough to either do a memcpy for trivially-copyable types, or a plain loop for non trivially-copyable types.
The last issue is your naming of the class vector. Note that there already is a std::vector in C++. Either change the name to something else, or place your class in its own namespace so that a name clash will not occur if you happen to #include <vector> somewhere.
Putting that all together, you will have this (not compiled, forgive any syntax errors):
#include <algorithm>
namespace myVector
{
template <typename T>
class vector
{
private:
// your member variables
public:
//...
vector(const vector &other) : capacity(other.capacity),
endIndex(other.endIndex), m_size(other.m_size)
{
storage = new T[capacity]();
std::copy(other.storage, other.storage + other.m_size, storage);
}
vector& operator=(const vector& other)
{
// see later
}
~vector()
{
delete [] storage;
}
//...
};
}
Then the main could be this:
#include <myvector>
int main()
{
myVector::vector<int> vec;
vec.push_back(5);
vec.push_back(55);
vec.push_back(500);
myVector::vector<int> vec1 = vec;
for (int i = 0; i < vec1.size(); i++)
{
std::cout << vec1[i] << std::endl;
}
return 0;
}
Once this is all done and corrected, to complete the rule of 3, the assignment operator can be simply this:
vector& operator=(const vector& other)
{
if ( &other != this )
{
vector temp(other);
std::swap(temp.capacity, capacity);
std::swap(temp.m_size, m_size);
std::swap(temp.endIndex, endIndex);
std::swap(temp.storage, storage);
}
return *this;
}
The above is using the copy/swap idiom
The problem is simple, but hard to see in your own code since you know what you want it to do. You could track it down by stepping through in a debugger and examining the value and address of storage scrupulously on every line.
Seriously, try doing that first.
OK, so here is it:
vector(const vector &other)
: storage(other.storage) // 1. copy the pointer, so this->storage is shared
, capacity(other.capacity)
, endIndex(other.endIndex)
, m_size(other.m_size)
{
// 2. declare a local variable called storage which shadows this->storage
T* storage = new T[capacity];
memcpy(storage, other.storage, sizeof(T) * capacity);
}
You do not want the storage to be shared, so you should never initialize storage(other.storage). There is literally no reason to do this in your code. If you just initialize it to nullptr you would have realized very quickly that the local variable in the constructor body was wrong.
Simply removing the T* from T* storage = ... will fix your immediate problem. All the other suggestions about using std::copy instead of memcpy, and how better to structure your code are good ones, and you should do those too.

Calling a constructor with parameters with new [] [duplicate]

I was wondering if it was possible to create an array of objects when the object needs things passed into it for the constructor. I want something like this:
MyClass *myVar;
myVar = new MyClass[num]; // I would like to specify the array size after declaration
int i = 0;
for(i = 0;i < num;i++)
myVar[i] = new MyClass(0,0); // I would also like to populate the array with new objects
I know that this works:
MyClass *myVar;
myVar = new MyClass[num];
but this only works when the constructor has nothing passed into it. Is what I am trying to do possible? If so, how do I do it?
EDIT: I found out how to do it with using arrays. Here is how I did it:
MyClass **myVar;
myVar = new MyClass *[num];
for(i = 0;i < num;i++)
myVar[0] = new MyClass(0,0);
I would use vectors and such but my teacher has told us to use basic arrays whenever possible. The above solution I actually got from some code my teacher wrote. Thank you all for your help!
MyClass *myVar;
myVar = new MyClass[num];
Actually in this form you cannot invoke constructor which takes parameter(s). It is not allowed by the language specification.
However, if you use std::vector, which I recommend you to use, then you can create a vector calling non-default constructor as:
#include <vector> //header file where std::vector is defined
std::vector<MyClass> arr(num, MyClass(10,20));
It creates a vector of num elements, each element is created by calling copy-constructor of the class, passing MyClass(10,20) as argument to it.
The vector is also good because now you dont need to manage memory yourself. Neither manual allocation, nor manual deallocation. Plus, you can know the number of elements by calling arr.size() anytime. You always know how many elements the vector contains. You can also add elements anytime, just by calling .push_back() member function as:
arr.push_back(MyClass(20,30));
And now you can access elements, just like you access array, i.e by using index:
f(arr[i]); // 0 <= i < arr.size();
Additionally, you can use iterators which facilitate idiomatic programming, enabling you to use various algorithmic functions from <algorithm> header as:
#include <algorithm> //header file where std::for_each is defined
std::for_each(arr.begin(), arr.end(), f);
where f is function which takes one argument of type MyClass& (or MyClass const &) depending on what you want to do in f.
In C++11, you can use lambda as:
std::for_each(arr.begin(), arr.end(), [](const MyClass & m)
{
//working with m
});
In C++0x, this grammar works, which can call the non-default constructor in new expression:
MyClass *myVar;
myVar = new MyClass[2]{{10, 20},{20, 30}};
But I doubt if it works when the number of elements in available only at run time.
The vector approach would be better, as shown in Nawaz's answer.
Pointer to pointer is equivalent to 1. array of pointers, and 2. vector<T*> vector of pointers. One way I've done this in the past is using a double pointer. This approach eliminates the overhead of vector data structure and preferred memory efficient is needed.
MyClass ** myvar;
myvar = new Myclass*[num]
for(int i = 0; i < num; i++){
*(myvar+i) = new Myclass(i);}
Works with pretty much any control structure you can imagine. The drawback is that the allocation of memory is not contiguous and my affect speed for large number of num.
You can do something like this too:
MyClass *myVar[num];
for(int i = 0; i < num; i += 1)
{
myVar[i] = new MyClass(0, 0);
}
Actually, you can use a placement new to handle this:
MyClass * myVar;
myVar = reinterpret_cast<MyClass *>(new char[num * sizeof(MyClass)]);
int i = 0;
for (i = 0; i < num; i++) {
new(&myVar[i]) MyClass(0,0);
}
#Nawaz answer is really good about using vectors, but didn't work for me because it create vector of the same objects (all of them reference to the same object)
class Graph
{
public:
Graph(long V); // none default Constructor
}
std::vector<Graph> myGraph;
for (int i = 0; i < T; i++) // read all graphs
{
Graph newGraph(N);
myGraph.push_back(newGraph);
}

How to use void* as a single variable holder? (Ex. void* raw=SomeClass() )

I am trying to make void* to hold a value (to avoid default constructor calling).
I want to:-
copy K to void* e.g. K k1; --> void* raw=k1;
copy void* to K e.g. void* raw; --> K k2=raw;
try not to break destructor and causes memory leak
don't use any dynamic allocation (heap, performance reason)
Here is what I tried:-
class K{
public: std::string yes="yes" ;
};
int main() {
//objective: k1->raw->k2 , then delete "raw"
void* raw[sizeof(K)]; //<--- try to avoid heap allocation
K k1;
static_cast<K>( raw)=k1; //<--- compile fail
K k2= static_cast<K>( raw);
std::cout<<k2.yes; //test
static_cast<K&>(raw)::~K(); //mimic destructor
return 0;
}
Question: Please provide a valid code that demonstrate a correct way to do this.
I found how to use placement new (https://stackoverflow.com/a/4756306/3577745 ), but not found how to use void* for a variable that is not an array.
C++ is new for me.
Edit :
I am writing a very custom collection (array).
Each element is encapsulated in a custom structure KCap kcap(with hold only 1 element, i.e. K).
Thus, I have to declare K k as a field of the encapsulator KCap.
However, I want to avoid default constructor of K, so I think void* can solve my issue.
What you are trying to do doesn't make sense. A void * is used to hold an arbitrary type of pointer, not an arbitrary type of other object. If you want to use storage for an arbitrary object type, use a char[].
Other problems with your code include that you need to ensure correct alignment of the raw storage, use reinterpret_cast to a reference rather than static_cast to a non-reference, your in-place destructor call syntax is wrong, and that you don't construct the K object in the "raw" storage. Here's a corrected version:
#include <string>
#include <iostream>
class K{
public: std::string yes="yes" ;
};
int main() {
//objective: k1->raw->k2 , then delete "raw"
alignas(alignof(K)) char raw[sizeof(K)]; //<--- try to avoid heap allocation
K k1;
new (reinterpret_cast<K *>(&raw)) K(k1); //<--- compile now succeeds :)
K k2= reinterpret_cast<K &>(raw);
std::cout << k2.yes << std::endl; //test
reinterpret_cast<K&>(raw).K::~K(); // call destructor
return 0;
}

Deep copy of a matrix-like class

I've got a class that shall behave like matrix.
So the usecase is something like:
Matrix matrix(10,10);
matrix[0][0]=4;
//set the values for the rest of the matrix
cout<<matrix[1][2]<<endl;
code:
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <sstream>
using namespace std;
class Matrix {
public:
Matrix(int x, int y);
class Proxy {
public:
Proxy(int* _array) : _array(_array) {
}
int &operator[](int index) const {
return _array[index];
}
private:
int* _array;
};
Proxy operator[](int index) const {
return Proxy(_arrayofarrays[index]);
}
Proxy operator[](int index) {
return Proxy(_arrayofarrays[index]);
}
const Matrix& operator=(const Matrix& othersales);
private:
int** _arrayofarrays;
int x, y;
};
Matrix::Matrix(int x, int y) {
_arrayofarrays = new int*[x];
for (int i = 0; i < x; ++i)
_arrayofarrays[i] = new int[y];
}
const Matrix& Matrix::operator=(const Matrix& othermatrix) {
new (this) Matrix(x, y);
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
_arrayofarrays[i][j] = othermatrix._arrayofarrays[i][j];
return *this;
}
int main() {
Matrix a(2, 3);
a[0][0] = 1;
a[0][1] = 2;
a[0][2] = 3;
a[1][0] = 4;
a[1][1] = 5;
a[1][2] = 6;
cout << a[1][2] << endl;
//prints out 6
const Matrix b = a;
cout << b[1][2] << endl;
a[1][2] = 3;
cout << a[1][2] << endl;
// prints out 3
cout << b[1][2] << endl;
// prints out 3 as well
}
By calling const Matrix b = a; I want to create new instance of Matrix, that will have the same values as a has in that moment. Nevertheless b is being affected by changing the values in a. So if I change some value in a, then it changes in b as well. And I don't want it to behave like this.
So I need to create a copy of b that would not be affected by a itself.
Those might be stupid question, but for me, as a java guy and a C++ newbie are all those stuff really confusing, so thanks for any helpful advices...
There are a few issues with your implementation. The simple one is the error you are getting...
In your Matrix class, operator[] is a non-const member function, which means that it can only be executed on non-const objects. Your operator= takes the right hand side object by const &, and thus you cannot call operator[] on it. The issue here is that you are not offering an implementation of operator[] that promises not to modify the object, once you add that to your type it should compile.
More important than that is the fact that you are leaking memory. When you call operator= on an object you are creating a different Matrix in place, without previously releasing the memory that it held. That is a memory leak.
The implementation of operator= is also not thread-safe. If allocation of memory for any of the internal arrays fails and throws an exception you are leaving your object in a state that is neither the original one nor a valid state. This is bad in itself.
Related to the previous, in as much as correcting one probably leads to the other, your implementation of operator= is not safe if there is aliasing, that is, it fails if you self-assign. The first line will leak the memory and create the new buffers, and from there on you will copy the new buffer into itself, loosing the original information.
Finally, the implementation of the type could be improved if you drop the requirement of using operator[] and use instead operator() with the two indices. User code will have to be adapted (and look less like a bidimensional array) but it provides a bit more freedom of representation (you can store the information internally in any way you want). At the same time, there is no need to allocate an array of pointers and then N arrays of int. You can perform a single memory allocation of NxM ints and do pointer arithmetic to address each location (this is independent of the use of operator[]/operator()), which will reduce the memory footprint and make the layout more compact, improving cache performance (not to mention reducing the number of dynamic allocations by a factor of M)
By calling const Matrix b = a; I want to create new instance of Matrix, that will have the same values of a in that moment. Nevertheless b is being affected by changing the values in a.
Well, this is yet another issue I missed in the first read. The expression const Matrix b = a; does not involve operator=, but rather the copy constructor. Another thing to google: Rule of the Three (basically, if you implement one of copy-constructor, assignment or destructor manually, you probably want to implement all three). Without defining your own copy constructor the compiler will implicitly define one for you that does a shallow copy (i.e. copies the pointers stored in Matrix but does not allocate memory for it). After the copy is made both Matrix share the same memory, and if your destructor releases the memory, you will run into Undefined Behavior when the second destructor runs and tries to delete [] the already deleted memory.

Overload operator '+' to add two arrays in C++

I want to add two arrays by simply writing:
int a[4] = {1,2,3,4};
int b[4] = {2,1,3,1};
int sum[4] = a + b;
I wrote this function but I got an error
int* operator+(const uint32& other) const{
uint32 sum[n];
for(int i=0; i<n; i++){
sum[i] = (*this[i]) + other[i];
}
return sum;
}
Could you help me on this? Thanks in advance.
Let's go through your code, piece by piece, and look at the problems:
int* operator+(const uint32& other) const{
You can't overload operators for built-in types, so this is doomed from the beginning
Even if you could do this (which you can't), it needs to take two parameters since it's non-member binary function.
uint32 sum[n];
You can't make variable-length arrays in C++ (assuming n isn't a compile-time constant) (note: G++ has some extensions that allow this, but it's non-standard C++)
for(int i=0; i<n; i++){
sum[i] = (*this[i]) + other[i];
There's no this pointer to begin with in this code (it's not a member function)...
const uint32& other is not an array/pointer to an array. It's a single reference to a single uint32. That means that other in this code is not an array/pointer to an array, and so you cannot do other[i] (it's like trying to do int x = 3; x[4] = 13;, which makes no sense).
}
return sum;
You're returning a pointer to a locally allocated array, which means this will result in undefined behavior, as the memory associated with sum is going to get annihilated when this function returns.
}
This is probably wrong, but it appears to work (C++11):
#include <iostream>
#include <array>
using namespace std;
template <class T>
T operator+(const T& a1, const T& a2)
{
T a;
for (typename T::size_type i = 0; i < a1.size(); i++)
a[i] = a1[i] + a2[i];
return a;
}
int main()
{
array<int,5> a1 = { 1, 2, 3, 4, 5 };
array<int,5> a2 = { 2, 3, 4, 5, 6 };
array<int,5> a3 = a1 + a2;
for (int i = 0; i < 5; i++)
cout << a1[i] << '+' << a2[i] << '=' << a3[i] << ' ';
cout << endl;
return 0;
}
Output (ideone):
1+2=3 2+3=5 3+4=7 4+5=9 5+6=11
I think the issue is that you're missing a way to pass in the length of the array. You might need to do something a bit more sophisticated. Something like:
class AddingVector : public std::vector<int>
{
public:
typedef AddingVector type;
type operator+(const AddingVector& rhs, const AddingVector& lhs)
{
/* validate that they're the same size, decide how you want to handle that*/
AddingVector retVal;
AddingVector::const_iterator rIter = rhs.begin();
AddingVector::const_iterator lIter = lhs.begin();
while (rIter != rhs.end() && lIter != lhs.end()) {
retVal.push_back(*rIter + *lIter);
++rIter;
++lIter;
}
return retVal;
}
}
You cannot do that. Non-member binary operators must take two arguments (you only provided one), so you could try this:
int* operator+(const uint32& a, const uint32& b)
But that can't possibly work either, since you want to add arrays, not single uint32 variables. So you would think that this would do it:
int* operator+(const uint32[] a, const uint32[] b)
or:
int* operator+(const uint32[4] a, const uint32[4] b)
But no go. It's illegal because you cannot have pointer types as both arguments in an operator overload. Additionally, at least one of the arguments must be a class type or an enum. So what you're trying to do is already impossible on at least two different levels.
It's impossible to do what you want. One correct way to go about it is to write your own class for an array that can be added to another one.
You cannot overload operators for types other than your own defined types. That is, if you create a class X, you can overload operators for X, but you cannot overload operators for arrays or pointers to fundamental types.
first is your code getting compiled properly, you have used 'n' directly in declaring array, is 'n' declared as constant..
And moreover you have taken a local variable in the function and returning it, well, this return a garbage form the stack, wat i can suggest is you malloc some memory and use it,, but again freeing it would be needed...
Hey, what you could do is,
Take a wrapper class "array"
class array
{
int *ipArr;
DWORD size;
};
then in constructor you can pass the size you want to have an array of
array(DWORD dwSize);
{
// then malloc memory of size dwSize;
}
Have an overloaded operator'+' for this class, that will have the above implementation of adding two int arrays,
Note here you will also need to overlaod the '=' assignment operator, so that our array class can you is directly..
now you can free the associated memory in the destructor
You have a few problems. The first is that you aren't passing in both arrays, and then you don't specify what n is, and the last is that you are trying to pass out a pointer to a local variable. It looks like you are trying to make a member operator of a class.
So basically you are trying to add the contents of an unspecified length array to an uninitialised array of the same length and return the stack memory.
So if you pass in pointers to the arrays and the length of the array and an output array then it would work, but you wouldn't have the syntax
sum = a + b;
it would be something like
addArray(&a, &b, &sum, 4);
To get the syntax you want you could make a class that wraps an array. But that is a much more complicated task.