Following my understanding of C++ convention, I have:
class BlockRepresentation : public FPRepresentation
{
private:
class Block
{
public:
int id;
int fpDimensions;
int* position; // pointers in question
int* blockDimensions; // pointers in question
~Block();
};
std::vector<Block> all_blocks;
public:
BlockRepresentation( int count, int dimensions, int volumn[] );
void AddBlock( int id, int position[], int dimensions[] );
std::string ToGPL();
};
where new blocks are created in AddBlock:
void BlockRepresentation::AddBlock( int id, int position[],
int dimensions[] )
{
Block newBlock;
newBlock.id = id;
newBlock.fpDimensions = fpDimensions;
newBlock.position = new int[fpDimensions]; // pointers in question
newBlock.blockDimensions = new int[fpDimensions]; // pointers in question
for (int i = 0; i < fpDimensions; ++i)
{
newBlock.position[i] = position[i];
newBlock.blockDimensions[i] = dimensions[i];
}
all_blocks.push_back( newBlock );
}
so I have the following destructor:
BlockRepresentation::Block::~Block()
{
delete[] position;
delete[] blockDimensions;
}
but then I get:
rep_tests(11039,0x7fff71390000) malloc: *** error for object 0x7fe4fad00240: pointer being freed was not allocated
Why should I not delete[] the 2 pointers here?
As was pointed out in the comments, you violated the rule of three, and the violation is very obvious:
{
Block newBlock;
// snip
all_blocks.push_back( newBlock );
}
When this function returns, the newBlock object goes out of scope, and its destructor will delete all the newed arrays.
But you push_back()ed this object. This constructs a copy of the object into the vector. Because your Block does not define a copy constructor, the default copy-constructor simply makes a copy of all the pointers to the newed arrays.
If you somehow manage to avoid dereferencing the no-longer valid pointers, or you survived that experience, you're not of the woods yet. That's because, when the vector gets destroyed, and its Blocks get destroyed, their destructors will, once again, attempt to delete the same newed arrays that were already deleted once before.
Instant crash.
There is nothing wrong with your Block destructor. It is doing its job, which is releasing the memory that is pointed to by your two int * member variables. The problem is that the destructor is being called on the same pointer value multiple times, which results in a double-free error.
The entity that causes this is the std::vector<Block>, since a std::vector will make copies of your Block object, and your Block object is not safely copyable.
Since the member variables of Block that are pointers are position and blockDimensions, the most painless way to alleviate this issue is to use std::vector<int> instead of int *, as demonstrated by this sample program.
However, if you really wanted to use int *, you would need to implement a user-defined copy constructor. In addition, a user-defined assignment operator would complement the copy constructor. This is what is called the Rule of Three.
#include <algorithm>
//...
class Block
{
public:
int id;
int fpDimensions;
int *position;
int *blockDimensions;
Block() : position(nullptr), blockDimensions(nullptr),
id(0), fpDimensions(0) {}
~Block()
{
delete [] position;
delete [] blockDimensions;
}
Block(const Block& rhs) : id(rhs.id), fpDimensions(rhs.fpDimensions),
position(new int[rhs.fpDimensions]),
blockDimensions(new int[rhs.fpDimensions])
{
std::copy(rhs.position, rhs.position + fpDimensions, position);
std::copy(rhs.blockDimensions, rhs.blockDimensions + fpDimensions,
blockDimensions);
}
Block& operator=(const Block& rhs)
{
Block temp(rhs);
std::swap(temp.position, position);
std::swap(temp.blockDimensions, blockDimensions);
std::swap(temp.id, id);
std::swap(temp.fpDimensions, fpDimensions);
return *this;
}
};
See the live sample here.
See all of the hoops we had to jump through to get the Block class to behave correctly when used within a std::vector, as opposed to simply using std::vector<int>?
Related
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 :-)
I have an Image class and initially I do not know the image dimensions, so I just initialize a data_ pointer to be an array of size 0. Later when I find the image information I reinitialize data_ to a new size. Will this create any problem in memory? and is there a cleaner way to do this?
Below is the class I have written:
class Image
{
private:
int numRows_, numCols_;
unsigned char* data_;
public:
Image() : numRows_(0), numCols_(0), data_(new unsigned char[0])
{}
void setData(int r, int c, unsigned char* data)
{
this->numRows_ = r;
this->numCols_ = c;
this->data_ = new unsigned char[r*c];
for (int i = 0; i < r*c; i++)
{
this->data_[i] = data[i];
}
}
int rows();
int cols();
unsigned char* data();
~Image();
};
Thanks in advance
This will in fact leak memory. The call to new allocates memory for the array, even if it is empty. As soon as you reassign data_, the previous array is leaked and can no longer be freed.
You can either make sure you delete[] any new[] you allocate, or just don't allocate an empty array and instead set data_ to nullptr until you have meaningful data to use.
An even better idea is don't allow the creation of an object in an invalid state, require the data in the constructor - see RAII:
In RAII, holding a resource is a class invariant, and is tied to
object lifetime: resource allocation (or acquisition) is done during
object creation (specifically initialization), by the constructor,
while resource deallocation (release) is done during object
destruction (specifically finalization), by the destructor.
If you do decide to keep setData, then as mentioned in comments, you also must make sure to delete[] existing data in setData before reassigning data_, in case the method is called more than once.
I think a cleaner way to do so will be using a vector:
std::vector<unsigned char> v; // vector with size 0
v.resize(r*c); // after size is known, just resize
I just started working with C++ and now I have a really basic question.
I wrote 2 classes:
Coordinate:
#include <stdio.h>
class Coordinate {
private:
int x;
int y;
public:
Coordinate(int a, int b) {
x = a;
y = b;
};
void printTest() {
printf("%d %d\n", x, y);
};
};
Test:
class Test {
private:
int q;
Coordinate *point;
public:
Test(int a, int b, int c) {
q = a;
point = new Coordinate(b, c);
};
virtual ~Test() {
delete point;
}
};
main function:
int main() {
Test *test = new Test(1, 2, 3);
// ...
delete test;
return 0;
}
In my main I worked with an object of the Test class. I wrote my own Test destructor but I am not sure if this destructor work like expected. Does it completly deallocte the memory from test? Or do I have to do something with the q attribute to deallocate it?
What you've done is correct, as far as it goes. Valgrind reports
==28151== HEAP SUMMARY:
==28151== in use at exit: 0 bytes in 0 blocks
==28151== total heap usage: 3 allocs, 3 frees, 72,736 bytes allocated
==28151==
==28151== All heap blocks were freed -- no leaks are possible
What you're missing is that the compiler has provided you with a default copy constructor and assignment operator. These will copy the pointer, rather than creating a new pointed-to value, so any time you copy a Test object you will then have two objects whose destructors will both try to delete the same storage. That's a double-free, and it can ruin your day.
To avoid that, C++ programmers use the Rule of Three or Rule of Five when writing classes, or - even better - the Rule of Zero, which says you shouldn't do any new or delete except in a class that exists only to own the storage.
Yes, this is the correct usage of a C++ destructor (your destructor in Test does not need the virtual keyword as there is no inheritance in your example).
As a rule of thumb every new should be followed by a delete, but when you're using class and instantiation it becomes more subtle than that. Following the Rule of Three or Five, when a class uses dynamic memory you should redefine the class destructor to deallocate accordingly, which you did, so great!
In your program execution, when delete test is invoked it will first deallocate the dynamic memory of point, before deallocating the dynamic memory you set in your main function with your test attribute. In this way you're not leaking memory (yay!) and your memory management has been done accordingly :)
You need a copy constructor to be sure that memory management is doing ok.
Because implicitly-generated constructors and assignment operators simply copy all class data members ("shallow copy").
And since you have pointers in your class with allocated data you really need it.
For example if in your part of main code: // ... you do a copy like:
Test testB = *test;
testB has a Coordinate pointer that is pointing to the same memory area that *test. It could cause problems, for example, when testB goes out of scope, it will free the same memory that *test is using.
Copy constructor should look like:
Test(const Test& other)
: point (new Coordinate(other.x, other.y))
, q(other.q)
{
}
With this you will be sure that every Coordinate* is initializated ok and released ok.
In your case, you don't need pointer
class Test {
private:
int q;
Coordinate point;
public:
Test(int a, int b, int c) : q(a), point(b, c) {};
};
int main() {
Test test(1, 2, 3);
// ...
return 0;
}
Would be enough.
If you want to allocate memory, I strongly suggest to use smart pointer or container instead:
class Test {
private:
int q;
std::unique_ptr<Coordinate> point;
public:
Test(int a, int b, int c) : q(a), point(std::make_unique_ptr<Coordinate>(b, c)) {};
};
int main() {
auto test = std::make_unique<Test>(1, 2, 3);
// ...
return 0;
}
In both way, you respect rule of 3/5/0.
In second case, you should probably want to provide copy constructor to your class:
Test(const Test& rhs) : q(rhs.q), point(std::make_unique<Coordinate>(*rhs.point)) {}
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.
I have a class containing a member pointer which is dynamically allocated in its constructor as follows:
class Record {
public:
Record(unsigned short numBytes, char* bufRecord);
~Record();
unsigned short size() {return m_numBytes;}
private:
unsigned short m_numBytes;
char* m_bufRecord;
};
Record::Record(unsigned short numBytes, char* bufRecord) {
m_numBytes = numBytes;
m_bufRecord = new char[numBytes];
for(unsigned short i=0; i<numBytes; i++)
m_bufRecord[i] = bufRecord[i];
}
Record::~Record() {
delete m_bufRecord;
}
It basically copies the input buffer into the dynamically allocated member buffer. I proceed to use this class as follows, in the constructor of another class:
class File {
public:
File(const char* fileName);
~File();
unsigned int numRecords() {return m_records.size();}
Record getRecord(unsigned int numRecord) {return m_gdsRecords[numRecord];}
private:
std::ifstream m_file;
std::vector<Record> m_records;
};
File::File(const char* fileName) : m_file(fileName, ios::in | ios::binary) {
while(!m_file.eof()) {
char bufNumBytes[2];
char* bufRecord;
unsigned short numBytes;
m_file.read(bufNumBytes, 2);
numBytes = (bufNumBytes[0] << 8) + bufNumBytes[1] - 2;
bufRecord = new char[numBytes];
m_file.read(bufRecord, numBytes);
Record record(numBytes, bufRecord);
m_records.push_back(record);
delete bufRecord;
}
}
However, when I instantiate this class, I get the following error, which seems to state that I'm double-freeing the m_bufRecord:
*** Error in `./a.out': double free or corruption (fasttop): 0x0000000001cb3280 ***
I'm guessing the problem lies with the insertion of a class containing a pointer to the vector element, and the destructor being called twice on the same pointer but I'm not sure how this happens. What am I doing wrong here?
This is a case of the Rule of three. If your class needs to free resources in the destructor, it generally needs to declare a copy constructor (and copy assignment operator), to either copy the owned resource, manage shared ownership or prevent being copied.
Record getRecord(unsigned int numRecord) {return m_gdsRecords[numRecord];}
This function returns a copy of the Record. So now you have two Records containing the same m_bufRecord pointer. Running the destructors on these Records will try to delete the same pointer value twice.