Vector of class objects - c++

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

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 :-)

Store array into dynamic memory

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.

Copying an array from a struct which is senŠµ through a function

I have want to send a struct to json->setInformation but my program crashes when i try to copy the array which is inside the struct. The rest of the data is okay its just the array which makes the crash occur.
info = data->getInformation();
json->setInformation(info);
getInformation returns a struct which i can read in main.cpp
when i try to send this struct to setInformation it crashes...
information.h which holds my struct
struct information{
String location;
String protocol;
uint8_t groupID;
uint8_t* data;
information& operator=(const struct information& that){
location = that.location;
protocol = that.protocol;
groupID = that.groupID;
for (int i = 0; i < 9; ++i){
data[i] = that.data[i];
}
return *this;
}
};
json.cpp
void JSON::setInformation(information data){
info->location = data.location;
info->protocol = data.protocol;
info->groupID = data.groupID;
// for (int i = 0; i < 9; ++i){
// info->data[i] = data.data[i];
// }
// Serial.print("after JSON: ");
// Serial.println(info->data[0]);
}
this code works fine but when i uncomment the for lop which should copy the array it crashes
Did you allocate memory for your uint8_t data* parameter before using it ?
Then remember to deallocate memory when you don't need it anymore, thus avoiding memory leaks.
Your object is passed by copy to the function, but you have no copy constructor.
Default copy constructor will not copy you raw pointer correctly. So either you declare and implement a copy constructor, either you replace your raw pointer (uint8_t*) by a vector (std::vector<uint8_t>) which is safely copyiable (then copying the object will become a valid operation).
Moreover, we can't see who's allocating/deallocating your raw pointer, but I suspect you are missing a destructor function too.
Your code breaks the rule of three which is the minimal requirement for any class you'll declare in C++.

wondering if I can use stl smart pointers for this

I currently have a c++ class as follows:
template<class T>
class MyQueue {
T** m_pBuffer;
unsigned int m_uSize;
unsigned int m_uPendingCount;
unsigned int m_uAvailableIdx;
unsigned int m_uPendingndex;
public:
MyQueue(): m_pBuffer(NULL), m_uSize(0), m_uPendingCount(0), m_uAvailableIdx(0),
m_uPendingndex(0)
{
}
~MyQueue()
{
delete[] m_pBuffer;
}
bool Initialize(T *pItems, unsigned int uSize)
{
m_uSize = uSize;
m_uPendingCount = 0;
m_uAvailableIdx = 0;
m_uPendingndex = 0;
m_pBuffer = new T *[m_uSize];
for (unsigned int i = 0; i < m_uSize; i++)
{
m_pBuffer[i] = &pItems[i];
}
return true;
}
};
So, I have this pointer to arrays m_pBuffer object and I was wondering if it is possible to replace this way of doing things with the c++ smart pointer perhaps? I know I can do things like:
std::unique_ptr<T> buffer(new T[size]);
Is using a vector of smart pointers the way to go? Is this recommended and safe?
[EDIT]
Based on the answers and the comments, I have tried to make a thread-safe buffer array. Here it is. Please comment.
#ifndef __BUFFER_ARRAY_H__
#define __BUFFER_ARRAY_H__
#include <memory>
#include <vector>
#include <mutex>
#include <thread>
#include "macros.h"
template<class T>
class BufferArray
{
public:
class BufferArray()
:num_pending_items(0), pending_index(0), available_index(0)
{}
// This method is not thread-safe.
// Add an item to our buffer list
void add(T * buffer)
{
buffer_array.push_back(std::unique_ptr<T>(buffer));
}
// Returns a naked pointer to an available buffer. Should not be
// deleted by the caller.
T * get_available()
{
std::lock_guard<std::mutex> lock(buffer_array_mutex);
if (num_pending_items == buffer_array.size()) {
return NULL;
}
T * buffer = buffer_array[available_index].get();
// Update the indexes.
available_index = (available_index + 1) % buffer_array.size();
num_pending_items += 1;
return buffer;
}
T * get_pending()
{
std::lock_guard<std::mutex> lock(buffer_array_mutex);
if (num_pending_items == 0) {
return NULL;
}
T * buffer = buffer_array[pending_index].get();
pending_index = (pending_index + 1) % buffer_array.size();
num_pending_items -= 1;
}
private:
std::vector<std::unique_ptr<T> > buffer_array;
std::mutex buffer_array_mutex;
unsigned int num_pending_items;
unsigned int pending_index;
unsigned int available_index;
// No copy semantics
BufferArray(const BufferArray &) = delete;
void operator=(const BufferArray &) = delete;
};
#endif
Vector of smart pointers is good idea. It is safe enough inside your class - automatic memory deallocation is provided.
It is not thread-safe though, and it's not safe in regard of handling external memory given to you by simple pointers.
Note that you current implementation does not delete pItems memory in destructor, so if after refactoring you mimic this class, you should not use vector of smart pointers as they will delete memory referenced by their pointers.
On the other side you cannot garantee that noone outside will not deallocate memory for pItems supplied to your Initialize. IF you want to use vector of smart pointers, you should formulate contract for this function that clearly states that your class claims this memory etc. - and then you should rework outside code that calls your class to fit into new contract.
If you don't want to change memory handling, vector of simple pointers is the way to go. Nevertheless, this piece of code is so simple, that there is no real benefit of vector.
Note that overhead here is creation of smart pointer class for each buffer and creation of vector class. Reallocation of vector can take up more memory and happens without your direct control.
The code has two issues:
1) Violation of the rule of zero/three/five:
To fix that you do not need a smart pointer here. To represent a dynamic array with variable size use a std:vector<T*>. That allows you to drop m_pBuffer, m_uSize and the destructor, too.
2) Taking the addresses of elements of a possible local array
In Initialize you take the addresses of the elements of the array pItems passed as argument to the function. Hence the queue does not take ownership of the elements. It seems the queue is a utility class, which should not be copyable at all:
template<class T>
class MyQueue
{
std::vector<T*> m_buffer;
unsigned int m_uPendingCount;
unsigned int m_uAvailableIdx;
unsigned int m_uPendingndex;
public:
MyQueue(T *pItems, unsigned int uSize)
: m_buffer(uSize, nullptr), m_uPendingCount(0), m_uAvailableIdx(0), m_uPendingndex(0)
{
for (unsigned int i = 0; i < uSize; i++)
{
m_buffer[i] = &pItems[i];
}
}
private:
MyQueue(const MyQueue&); // no copy (C++11 use: = delete)
MyQueue& operator = (const MyQueue&); // no copy (C++11 use: = delete)
};
Note:
The red herring is the local array.
You may consider a smart pointer for that, but that is another question.

Array-style Linked list implementation C++

I am given a task to simulate a linked list structure, but using an array of Nodes rather than an actual linked list. When I call my append function, I want to check to see if my existing array is full, and if it is, I want to double the array size, and append my Node to the end of the "list" (array).
I am having trouble doubling my array size.
To give you context, here is my some of my .h file:
...
const int NULL_INDEX = -1;
struct Node {
char info;
int next;
};
class LList1 {
private:
Node free [4];
// When more memory is called for, the array will double in size
// returns true if reallocation of memory was successful
bool doubleSize();
.
.
.
}
and here is the part of my .cpp file that tries to double the array size:
bool LList1::doubleSize() {
Node* newArray = new Node[this->length()*2];
memcpy(newArray, free, this->length()*2);
free = newArray;
return true;
}
I also tried using realloc and other functions. I keep having the same problem.
The line
"free = newArray"
keeps giving me this error in XCode: "Array type 'Node[4]' is not assignable"
Please give me some insight into a better way to do this. All solutions online seem to work fine for arrays of ints, but not for my array of Nodes.
Much appreciated.
A couple of things are incorrect in your code:
Your free property is a static array. In your case you need a dynamic one, with proper constructor.
The memcpy command takes the size in bytes, hence you need to multiply by sizeof(Node).
Perhaps it was intended, but the doubleSize() method was private.
Here is a corrected version of the code that compiles and runs:
...
const int NULL_INDEX = -1;
struct Node {
char info;
int next;
};
class LList1 {
public:
LList1();
~LList1();
int getLength();
bool doubleSize();
private:
int length;
Node* free;
// When more memory is called for, the array will double in size
// returns true if reallocation of memory was successful
};
int LList1::getLength() {
return this->length;
}
LList1::LList1() {
this->free = new Node[4]; // Default size
this->length = 4;
}
LList1::~LList1() {
delete []this->free;
}
bool LList1::doubleSize() {
Node* newArray = new Node[this->length*2];
memcpy(newArray, free, this->length * sizeof(Node));
free = newArray;
this->length *= 2;
return true;
}
int main(int, char **) {
LList1 l;
std::cout << "Original length: " << l.getLength() << std::endl;
l.doubleSize();
std::cout << "After doubling length: " << l.getLength() << std::endl;
return 0;
}
You are getting confused between arrays and pointers. Your variable free is a constant pointer which cannot be reassigned. You need to change Node free [4] to Node *free if you want to modify its value.
C/C++ int[] vs int* (pointers vs. array notation). What is the difference?