Store array into dynamic memory - c++

I'm passing an array to a constructor. Constructor has two parameters, pointer to int called data and int which is size of an array.
I'm allocation dynamic memory in constructor definition for this array and passing array pointer to this storage.
Last but one step is printing values in array through the pointer which is pointing to the first int value of this array.
The last step is freeing up memory in destructor delete [] data. In this step I got an error message: Debug Assertion Failed! Expression: _CrtlsValidHeapPpinter(block).
I'm very new in C++ so I'm struggling what I did wrong in below program. Could you give me a hint, please?
#include <iostream>
class Test
{
private:
int* data;
int size;
public:
// constructor and destructor
Test(int* d, int s);
~Test();
// few void methods
void display_data(int size)
{
for (int i{ 0 }; i < size; ++i)
{
std::cout << data[i] << " ";
}
std::cout << std::endl;
}
};
Test::Test(int* d, int s)
: data{nullptr}, size(s)
{
data = new int[s];
data = d;
}
Test::~Test()
{
std::cout << "Destructor is freeing memory" << std::endl;
delete[] data;
}
int main()
{
int data_array[5]{ 2,8,6,10,20 };
Test* t1 = new Test(data_array, 5);
t1->display_data(5);
delete t1;
return 0;
}

In yout Test::Test constructor you don't copy the array, you just copy the pointer. You need to use std::copy or memcpy (C-style) to copy the contents of d into data.
However, I would recommend to use STL containers (i.e., std::vector) instead of raw pointers. It will allow you to get rid of manual resource management (new/delete), which is error-prone and redundant.

You need to copy the data here. Instead of :
data = new int[s];
data = d;
Which creates an array and then forgets about it. This would lead to the array being deleted multiple times!
Copy the content of your array:
std::copy(d, d+s, data);
Or even better, use std::vector.

Related

It is legal this approach for create a local variable in C++

I'm new to C++ and try to understand how to create and use a class in C++.
For this I have the following code:
class MyClass
{
public:
MyClass()
{
_num = 0;
_name = "";
}
MyClass(MyClass* pMyClass)
{
_num = pMyClass->_num;
_name = pMyClass->_name;
}
void PrintValues() { std::cout << _name << ":" << _num << std::endl; }
void SetValues(int number, std::string name)
{
_num = number;
_name = name;
}
private:
int _num;
std::string _name;
};
int main()
{
std::vector<MyClass*> myClassArray;
MyClass myLocalObject = new MyClass();
for (int i = 0; i < 3; i++)
{
myLocalObject.SetValues(i, "test");
myClassArray.push_back(new MyClass(myLocalObject));
}
myClassArray[1]->PrintValues();
// use myClassArray further
}
I get a similar example from the internet and try to understand it.
My intentions is to populate myClassArray with new class objects.
If I compile the code above using VisualStudio 2022 I get no errors, but I'm not sure it doesn't produce memory leaks or if there is a faster and simple approach.
Especially I do not understand the following line:
MyClass myLocalObject = new MyClass();
myLocalObject is created on the stack but is initialized with a heap value (because of the new). If new operator is used where should delete must apply?
Thank you for any suggestions!
You have a memory leak at MyClass myLocalObject = new MyClass();, since the dynamically-allocated object is used to converting-construct the new myLocalObject (this was almost but not quite a copy constructor) and then the pointer is lost.
You also didn't show the code using the vector, but if it doesn't delete the pointers inside, you will have more memory leaks.
There's no reason to have an almost-copy-constructor; the compiler has provided you with a better real copy-constructor.
The faster and simpler approach is to recognize that this code doesn't need pointers at all.
class MyClass
{
public:
MyClass()
: _num(), _name() // initialize is better than assignment
{
//_num = 0;
//_name = "";
}
// compiler provides a copy constructor taking const MyClass&
//MyClass(MyClass* pMyClass)
//{
// _num = pMyClass->_num;
// _name = pMyClass->_name;
//}
void PrintValues() { std::cout << _name << ":" << _num << std::endl; }
void SetValues(int number, std::string name)
{
_num = number;
_name = name;
}
private:
int _num;
std::string _name;
};
int main()
{
std::vector<MyClass> myClassArray; // not a pointer
MyClass myLocalObject; // = new MyClass(); // why copy a default instance when you can just default initialize?
for (int i = 0; i < 3; i++)
{
myLocalObject.SetValues(i, "test"); // works just as before
myClassArray.push_back(/*new MyClass*/(myLocalObject)); // don't need a pointer, vector knows how to copy objects
// also, this was using the "real" copy-constructor, not the conversion from pointer
}
myClassArray[1].PrintValues(); // instead of ->
// use myClassArray further
}
for cases where a pointer is necessary, for example polymorphism, use a smart pointer:
std::vector<std::unique_ptr<MyClass>> myClassArray; // smart pointer
myClassArray.push_back(make_unique<MyDerivedClass>(stuff));
std::unique_ptr will automatically free the object when it is removed from the vector (unless you explicitly move it out), avoiding the need to remember to delete.
There are basically 2 ways to instantiate objects of classes.
Dynamic allocation (on heap)
MyClass* myLocalObject = new MyClass(); // dynamically allocates memory and assigns memory address to myLocalObject
Example for your loop:
class MyClass
{
private:
int _num;
std::string _name;
public:
// let's add an additional constuctor having default values
// that makes it easier later on
// if parameters are passed, they are used, or the defalt values, if not
// can call it like MyClass(), MyClass(123), or MyClass(456,"hello")
// you might want to pass larger data as reference, to avoid copying it
MyClass(int num=0, std::string name = "some default text")
: _num(num), _name(name)
{}
};
std::vector<MyClass*> myClassArray; // your array of pointers
for (int i = 0; i < 3; i++)
myClassArray.push_back(new MyClass(i, "test"));
// delete
for (auto& pointerToElement : myClassArray) // get a reference to each element (which is a pointer)
delete pointerToElement; // delete element (call's destructor if defined)
In that case you must delete myLocalObject; or you get a memory leak.
Instead of dealing with raw pointers, especially when new to C++, I recommend to use smart pointers, that deal with memory management for you.
Automatic allocation (on stack when possible)
MyClass myLocalObject = MyClass(); // automatically allocates memory and creates myLocalObject
This happens usually on stack (if possible). That's much faster and you don't have to deal with dynamic memory management
Example for your loop:
std::vector<MyClass> myClassArray; // now "containg" the memory of objects itself
for (int i = 0; i < 3; i++)
{
myClassArray.emplace_back(i, "test"); // we use emplace_back instead to construct instances of type MyClass directly into the array
}
// no deletion required here
// destructors of each element will be called (if defined) when myClassArray is deleted automatically when out of scope
There are other ways, like dynamic stack allocation and other black magic, but recommend to focus on "the standard".
In case of dealing with large amounts of data, you might want to use std::vector::reserve. In combination with automatic/stack allocation that helps to speed up a lot by limiting memory allocations to 1 at all instead of 1 per element.
Hope that helps :-)

dynamic array in c++: valgrind leak

I'm trying to implement a dynamic array in c++. once it becomes full, its size is doubled and is copied to the double-sized array.
it looks fine but Valgrind says I have a leak.
I should say that I'm not allowed to use any of c++ STL structures- that's why I'm using new[] and delete[] operators.
this is my code:
template<class T>
class DynamicArray
{
int size;
int numOfElements;
T* arr;
public:
DynamicArray(int size) :
size(size), numOfElements(0)
{
arr = new T[size];
}
;
int getSize()
{
return size;
}
int getNumberOfElements()
{
return numOfElements;
}
void insert(T element)
{
arr[numOfElements++] = element;
if (numOfElements == size)
{
T* extended_array = new T[size * 2];
for (int i = 0; i < numOfElements; i++)
{
extended_array[i] = arr[i];
}
delete[] arr;
arr = extended_array;
size = size * 2;
}
}
T& operator[](int i)
{
if (!((i >= 0) && (i < size)))
throw arrayOutOfBoundsException();
return arr[i];
}
~DynamicArray()
{
delete[] arr;
}
class arrayOutOfBoundsException: std::exception
{
};
};
My main program is:
using std::cout;
using std::endl;
void printIntArray(DynamicArray<int> arr){
cout << "size: " << arr.getSize() << "; " << "numOfElemnts: " << arr.getNumberOfElements() << endl;
cout << "array: ";
for(int i=0; i<arr.getNumberOfElements(); i++){
cout << " " << arr[i];
}
cout << endl << endl;
}
int main() {
DynamicArray<int> arr(5);
printIntArray(arr);
arr.insert(1);
arr.insert(2);
arr.insert(3);
printIntArray(arr);
arr.insert(4);
printIntArray(arr);
arr.insert(5);
printIntArray(arr);
arr.insert(6);
printIntArray(arr);
arr.insert(7);
arr.insert(8);
arr.insert(9);
printIntArray(arr);
arr.insert(16);
printIntArray(arr);
arr[9] = 901;
arr[0] = 101;
printIntArray(arr);
**valgrind shows me this error- when the destructor is compiled as comment:
==3954== 80 bytes in 1 blocks are definitely lost in loss record 1 of 1
==3954== at 0x4A07192: operator new[](unsigned long) (vg_replace_malloc.c:363)
==3954== by 0x40103E: DynamicArray<int>::insert(int) (DynamicArray.h:41)
==3954== by 0x400DBC: main (main.cpp:44)**
Can anybody tell me what I was doing wrong? am I misusing "delete[]"? or the destructor?
thanks
The behaviour described by the asker is impossible or
when the destructor is compiled as comment:
means the destructor has been commented out and this is causing the leak. This has been confirmed in a comment. Without the destuctor the last allocation will never be put away.
The Asker's real problem is a Rule of Three Violation.
The short version goes something like this:
If a class requires a user defined copy constructor, assignment operator, or destructor it almost always requires all three.
More on that here: What is The Rule of Three?
In this case,
void printIntArray(DynamicArray<int> arr)
accepts arr by value. This means arr is a copy of the value passed in. In the absence of a custom copy constructor the arr inside printIntArray will point to the same allocation as the source. The copy will be destroyed at the end of printIntArray, and the destructor will delete the allocation, leaving the source pointing to invalid memory so...
DynamicArray<int> arr(5); // allocated storage inside arr
printIntArray(arr); // made a copy of arr that points to same storage.
// Storage freed when copy destroyed
arr.insert(1); // invokes undefined behaviour writing into invalid memory
arr.insert(2); // same
arr.insert(3); // same
printIntArray(arr); // copies arr again. This copy is pointing to the same invalid memory
// and will try to free the allocation a second time when the
// copy is destroyed
The program will almost certainly crash here, making it impossible to leak from the users code. But because the program crashed, Crom only knows what behind-the-scenes structures the runtime was using were not correctly put away.
Whatever happened, as of
arr.insert(1);
the program was deep in Undefined Behaviour and whatever happens after that is anybody's guess. Memory leaks are the least of your worries.
Fixing: Satisfy the Rule of Three
Implement a copy constructor and an assignment operator (We'll ignore the Rule of Five for now.)
You could change
void printIntArray(DynamicArray<int> arr)
to pass by reference
void printIntArray(DynamicArray<int> & arr)
and then
DynamicArray(const DynamicArray &) = delete;
DynamicArray& operator=(const DynamicArray &) = delete;
and disable all copying, but this seems a bit draconian.
Instead lets use Copy and Swap because it's simple and easy to understand. Note that it can also be inefficient, so it's not always the right tool. Here it fits what we want.
DynamicArray(const DynamicArray & src) :
size(src.size), numOfElements(src.numOfElements), arr(new T[size])
{
for (int i = 0; i < numOfElements; i++)
{
arr[i] = src.arr[i];
}
}
DynamicArray& operator=(const DynamicArray src)
{
std::swap(size, src.size);
std::swap(numOfElements, src.numOfElements);
std::swap(arr, src.arr);
return *this;
}
And because who wants to copy they don't need to we'll still
void printIntArray(DynamicArray<int> & arr)
as soon as we're done testing that the copy constructor works correctly.

C++ double free error from function copy

I'm working through the Stroustrup C++ 11 book, and I ran into a double free exception. I understand that it's freeing the memory twice, but what I don't understand is why it's happening for a function that's passing by copy:
#include <iostream>
using namespace std;
namespace ALL_Vector {
class Vector {
public:
// Intitialize elem and sz before the actual function
Vector(int size) :elem {new double[size]}, sz {size} {};
~Vector() {delete[] elem;};
double& operator[](int i) {
return elem[i];
};
int size() {return sz;};
private:
double* elem;
int sz;
};
void print_product(Vector& y) {
double result {1};
for (auto x = 0; x < y.size() ; x++){
if (y[x] > 0) {result *= y[x]; };
}
cout << "The product of Vector y is: " << result << ", or so it would appear ;)\n";
}
}
/*
Self test of the Vector class.
*/
int main(){
ALL_Vector::Vector myVector(15);
cout << "The size of Vector y is: " << myVector.size() << "\n";
myVector[0] = 12;
myVector[2] = 7;
myVector[3] = 19;
myVector[4] = 2;
ALL_Vector::print_product(myVector);
return 0;
}
print_product() is taking the Vector class and creating a new Vector with duplicated contents? Why would this cause a double free? I'm assuming that RIIA in this instance is somehow interacting with the Vector::~Vector(), something like a race condition?
I know if I change this to pass it's argument by reference it will avoid the double free. I'm trying to better understand the issue with passing by copy.
Thanks!
Actually you are calling print_product with a reference to myVector, so everything is fine.
Troubles begin with passing myVector by value because default copy constructor will copy elem pointer instead of duplicating the whole array.
Both ALL_Vector::Vector elem pointer will refer to same memory storage and thus be deleted twice.
To tackle this issue, you have to implement copy constructor to create a new array and copy all elements.
If you pass Vector per value, the copy constructor is called, not the constructor you have implemented.
In this case, elem is not duplicated but the pointer is copied in the new object and then deleted twice by the destructor.
You have to implement a copy constructor that allocate a new elem and copy all elements.

What's wrong with this use of placement new[]? do

Consider the program below. It has been simplified from a complex case. It fails on deleting the previous allocated memory, unless I remove the virtual destructor in the Obj class. I don't understand why the two addresses from the output of the program differ, only if the virtual destructor is present.
// GCC 4.4
#include <iostream>
using namespace std;
class Arena {
public:
void* alloc(size_t s) {
char* p = new char[s];
cout << "Allocated memory address starts at: " << (void*)p << '\n';
return p;
}
void free(void* p) {
cout << "The memory to be deallocated starts at: " << p << '\n';
delete [] static_cast<char*> (p); // the program fails here
}
};
struct Obj {
void* operator new[](size_t s, Arena& a) {
return a.alloc(s);
}
virtual ~Obj() {} // if I remove this everything works as expected
void destroy(size_t n, Arena* a) {
for (size_t i = 0; i < n; i++)
this[n - i - 1].~Obj();
if (a)
a->free(this);
}
};
int main(int argc, char** argv) {
Arena a;
Obj* p = new(a) Obj[5]();
p->destroy(5, &a);
return 0;
}
This is the output of the program in my implementation when the virtual destructor is present:
Allocated memory address starts at: 0x8895008
The memory to be deallocated starts at: 0x889500c
RUN FAILED (exit value 1)
Please don't ask what the program it's supposed to do. As I said it comes from a more complex case where Arena is an interface for various types of memory. In this example the memory is just allocated and deallocated from the heap.
this is not the pointer returned by the new at line char* p = new char[s]; You can see that the size s there is bigger than 5 Obj instances. The difference (which should be sizeof (std::size_t)) is in additional memory, containing the length of the array, 5, immediately before the address contained in this.
OK, the spec makes it clear:
http://sourcery.mentor.com/public/cxx-abi/abi.html#array-cookies
2.7 Array Operator new Cookies
When operator new is used to create a new array, a cookie is usually stored to remember the allocated length (number of array elements) so that it can be deallocated correctly.
Specifically:
No cookie is required if the array element type T has a trivial destructor (12.4 [class.dtor]) and the usual (array) deallocation function (3.7.3.2 [basic.stc.dynamic.deallocation]) function does not take two arguments.
So, the virtual-ness of the destructor is irrelevant, what matters is that the destructor is non-trivial, which you can easily check, by deleting the keyword virtual in front of the destructor and observe the program crashing.
Based on chills' answer, if you want to make it "safe":
#include <type_traits>
a->free(this - (std::has_trivial_destructor<Obj>::value ? 1 : 0));

Vector of class objects

I have created a vector of class objects. The following program crashes with
"Pointer being freed was not allocated".
I have deep copied as well. I don't see where the double delete is happening. What am I missing ?.
#include <iostream>
#include <vector>
using namespace std;
enum MessageType { HEADER, DATA, CLOSE};
typedef class bufferElement{
public:
char *buffer ; //The actual data
int64_t length; //length of the data
MessageType messagetype;
/**
* Copy constructor for the structure
*/
bufferElement(const struct bufferElement &toCopy)
{
std::cout << "Copying the buffer vector - Copy Constructor for buffer" << std::endl;
buffer = new char[toCopy.length];
memcpy(buffer,toCopy.buffer,toCopy.length);
length = toCopy.length;
messagetype = toCopy.messagetype;
}
bufferElement()
{
buffer = NULL;
length =0;
messagetype = HEADER;
}
/**
* Initialises the vector element
* #param messagetype
* what type of message is the particular element.
* #param element
* The buffer element
* #param length_t
* The length/size of the buffer element
*/
bufferElement(char *element, int64_t length_t, MessageType messagetype_t) //constructor
{
std::cout << "The buffer element is Initialized" << std::endl;
buffer = new char[length_t];
messagetype = messagetype_t;
length = length_t;
memcpy(buffer, element, length_t);
}
~bufferElement()
{
std::cout << "Freeing the buffer in the vector - Destructor" << std::endl;
delete buffer;
buffer = NULL;
}
} messageHolder;
int main()
{
vector<messageHolder> v;
for(int64_t i=0; i< 1000000000000000000; i++)
{
int size = rand()%10000+5;
char *test = new char[size];
messageHolder m(test, size, HEADER );
v.push_back(m);
if(rand()%3)
{
v.erase(v.begin());
}
}
return 0;
}
I haven't looked at your code in detail, but if you think you need a copy constructor, you also need an assignment operator. And, why, why, why write this stuff anyway? Why not use std::string? Do you feel the need to write your own floating point types? No, I didn't think so.
Use delete[] instead of delete, since you are freeing an array.
By the way, in main(), you should also invoke delete[] test;, otherwise, you'll get a memory leak.
In general I would avoid using objects with pointers as members (like buffer in your bufferElement) as types in vector (or any other stl container for that matter) without a copy constructor AND an assignment operator. If the destructor frees that pointer it's a recipe for destruction. You should eighter
a) provide both the copy ctr and the assignment op
OR
b) don't use pointers (use smart pointers like boost::scoped_ptr or boost:shared_ptr or even in your case auto_ptr) which I favor more