I create a 2D array of Nodes (Node class is in a separate file) and i'm wondering how to deallocate exactly this (below). I've tried many ways and mem leaks still appear.
board = new Node * [r];
//creats a column for each element in the row
for(int i = 0; i < r; i++) {
board [i] = new Node [c];
}
(r is the rows and c is the cols)
I've done this:
for(int i = 0; i < r; i++) {
delete [] board[i];
}
delete [] board;
But apparently it's not enough
The code you have is correct and sufficient. However, it would be better to use RAII so that you do not need to explicitly call delete at all (perhaps not even new). For example, you could create a std::vector<std::vector<Node>>, or better still, some sort of matrix class (not in the standard library, unfortunately).
Your solution is the correct way to free two dimensional array. However you may still get a memory leak if Node uses dynamic memory and it's destructor is not properly defined.
As others have said, you're correctly pairing up all your new[]s and delete[]s: assuming no errors occur, the memory allocated by this code will be correctly deallocated.
The only issue is that errors may occur, and in particular exceptions may be thrown:
new[] can throw an exception if it fails to allocate memory (doesn't normally happen on desktop OSes, but you should still write code as if it does.)
Node's constructor may throw. Even if you've designed the constructor not to throw you generally shouldn't take advantage of that knowledge. Just write code as if throws.
In fact, you should just generally write code as if pretty much anything can throw. For more detailed info on writing exception safe code, and on what the exceptions to this rule are you can read the info at http://exceptionsafecode.com
The best way to make this code exception safe is to use RAII. For example use a vector instead of new[]/delete[].
Using an array of pointers and a separate allocation for each row makes sense for 'ragged' arrays, where each row can be a different length. In your case you have rectangular array, so you can use a single allocation for the whole thing.
std::vector<Node> board(rows*columns);
board[row_index*columns + column_index] // replaces board[row_index][column_index]
You can hide the implementation by putting this in a class:
class Board {
std::vector<Node> board_data;
public:
const int rows;
const int columns;
Board(int rows_, int columns_)
: board_data(rows_*columns_)
, rows(rows_)
, columns(columns_)
{}
struct board_index { int row, column; };
Node &operator[](board_index i) {
assert(0 <= i.row && i.row < rows);
assert(0 <= i.column && i.column < columns);
return board_data[i.row * columns + i.column];
}
};
Board board(r, c);
with the above implementation you replace board[i][j] with board[{i, j}].
board[{i, j}] = ... // assign to a place on the board
board[{i, j}].foo(); // call a Node method
std::cout << board[{i, j}]; // print a Node
// etc.
Related
I am building a class called ParticleMatrix that stores a two dimensional array of the object Ball. I want to dynamically allocate space for them. The code looks like this.
/*
* allocateParticle takes a width w, height h, restlength RL then allocates space for
* and constructs a 2D array of Particles of subclass Ball.
*/
void ParticleMatrix::allocParticles(int w, int h, float RL)
{
// Gets the number of particles in the xDirection
xPart = getNrPart(w,RL);
// Gets the number of particles in the yDirection
yPart = getNrPart(h,RL);
// Allocates a row of pointers to pointers.
ballArray = new Ball*[xPart];
// The ID of the particles.
int ID = 0;
// For every particle in the xDirection
for(int x = 0; x<xPart; x++)
{
// Allocate a row of Ball-pointers yPart long.
ballArray[x] = new Ball[yPart];
// For every allocated space
for(int y = 0; y<yPart; y++)
{
// Construct a Ball
ballArray[x][y] = Ball( ID, RL*(float)x, RL*(float)y);
ID++;
}
}
}
The problem occurs with the line "ballArray[x] = new Ball[yPart]". CodeBlocks gives me the compiler error " error: no matching function for call to 'Ball::Ball()' ".
I have 4 constructors for Ball with different signatures, none looking like: "Ball()".
I have tried with adding a constructor "Ball::Ball()" and it compiles then but I feel like I should be able to just allocate space for an object and later instantiate them.
What I'm wondering is: Why can't I allocate space for the object Ball without having a constructor "Ball::Ball()" in the code above?
and: If it is possible in some way to allocate space without the constructor "Ball::Ball()", how would I go about doing it?
I know I can create the constructor "Ball::Ball()" and give the objects some dummy values then later set them to their required values, but I feel uncomfortable doing this since I don't know why I couldn't just "Allocate space -> instantiate object". I hope I was able to explain my issue. Thanks!
Instead of new T, that gets memory and calls ctor, you can call operator new with a size you supply. The only provides you memory and nothing else. Then you can call placement new on properly calculated locations, that will invoke only your ctor. On the location you posted instead of allocating anew. Search google for the provided terms to see examples.
But normally you're not supposed to do any of that, your task can be done well using a std::vector<Ball> with way less effort and more security.
Another "C++ way" of doing this is using std::allocator.
It provides you allocate and deallocate which only reserve memory without constructing elements.
std::allocator<Ball*> ball_ptr_allocator;
std::allocator<Ball> ball_allocator;
Ball ** ptr = ball_ptr_allocator.allocate(10);
for (size_t x=0; x<10; ++x)
{
ptr[x] = ball_allocator.allocate(10);
for (size_t y=0; y<10; ++y)
{
ball_allocator.construct(&ptr[x][y], ID, RL*(float)x, RL*(float)y);
// if you do not have access to C++11 use this:
// ball_allocator.construct(&ptr[x][y], Ball(ID, RL*(float)x, RL*(float)y));
++ID;
}
Note several issues here:
I'd generally suggest to use unsigned types for sizes (like size_t for example).
If you make the allocator a member you can access is in the destructor etc. to deallocate stuff again. std::allocator<Ball> m_ballAlloc;
You have to (somehow) keep track of the constructed elements and allocated memory. If one of the constructions will throw an exception you should be able to clean up the constructed elements and deallocate the allocated memory.
For the deallocation tracking you can go with an additional loop in your allocParticles
for(size_t x = 0; x<xPart; x++) ballArray[x] = nullptr;
Now you know that every ballArray[i] that is not a nullptr needs to be deallocated.
But you'll have to destroy your elements first.
If you make your ID a member variable of the class you can use it to destroy constructed elements (since it's only incremented after element construction).
I wrote a destructor example with respect to ballArray destruction only, note that you'll may have to take care of other resources, too, if present.
~ParticleMatrix (void)
{
// check this here and set ballArray to nullptr upon construction
// of the ParticleMatrix
if (ballArray != nullptr)
{
// start to destroy the Balls
size_t destroycounter(0U);
for(size_t x = 0; x<xPart; x++)
{
for(size_t y = 0; y<yPart; y++)
{
if (destroycounter < ID)
{
m_ballAlloc.destroy(&ballArray[x][y]);
++destroycounter;
}
}
}
// deallocate 2nd dimension arrays
for(size_t x = 0; x<xPart; x++)
{
if (ballArray[x] != nullptr) m_ballAlloc.deallocate(ballArray[x], yPart);
}
// deallocate first dimension
delete [] ballArray;
}
}
In C++, the operator new does not just allocate space for a variable, but also constructs it. If you don't have a default construtor Ball::Ball(), then you cannot construct each object in the array. There is no "just allocate space" in C++, in principle...
I have a vector of pointers like so:
vector<Item*> items;
I want to clear it. I've tried:
for (unsigned int i = 0; i < items.size(); i++)
delete items.at(i);
items.clear();
,
while (!items.empty())
{
delete items.back();
items.pop_back();
}
,
while (!items.empty())
{
delete items.at(0);
items.erase(items.begin());
}
, and
while (!items.empty())
delete items.at(0);
Every single one of these blows up for some reason or another, including deletion of already deleted objects and out of range vector iterators.
What do I do? I want to be able to reuse that same vector and add more Item pointers into it later. Just using delete without clearing still leaves junk pointers in there, right?
EDIT: Okay, I've switched to shared_ptrs. Now I have
vector<shared_ptr<Item> > items;
Yet, when I do items.clear(); , I get the error "vector iterators incompatible". What am I still doing wrong?
I ran a test with all your ways of deleting stuff, and one of them simply doesn't work. See the code below for the comments on them.
To answer your question "what do I do," here is what I do when I seg-fault on a delete:
1) Make sure the memory is mine (do I know where the corresponding new is)?
2) Make sure I didn't delete the memory already (if I did, even if it WAS mine, it isn't now).
3) If you're pretty sure your seg-fault is caused by a single section of your code, break it out into a small test case in another project (kind of like you did in your question). Then play with it. If you had run your code examples up top in a small project you would have seen the seg-fault on the last one, and you would have noted the deletes worked in every other case. Breaking the code down like this would have let you know that you need to trace how you are storing these in your vector to see where you are losing ownership of them (via delete, or passing them to something that deletes them, etc...).
A side note: as others are saying, if you can use smart pointers do so, they will take care of the memory management for you. However, please continue your study here and understand how to use pointers that are dumb. There are times when you can not import boost, or have QT do your memory management for you. Also, there are times when you MUST store pointers in a container so don't be afraid to do that either (IE: QT developers STRONGLY suggest using pointers to store widgets instead of references or anything of the sort).
#include <vector>
using namespace std;
class Item
{
public:
int a;
};
int main()
{
vector<Item *> data;
for(int x = 0; x < 100; x++)
{
data.push_back(new Item());
}
//worked for me, and makes sense
for(int x = 0; x < 100; x++)
{
delete data.at(x);
}
data.clear();
for(int x = 0; x < 100; x++)
{
data.push_back(new Item());
}
//worked for me, and makes sense
while (!data.empty())
{
delete data.back();
data.pop_back();
}
data.clear();
for(int x = 0; x < 100; x++)
{
data.push_back(new Item());
}
// //worked for me, and makes sense
while (!data.empty())
{
delete data.at(0);
data.erase(data.begin());
}
for(int x = 0; x < 100; x++)
{
data.push_back(new Item());
}
// //This one fails, you are always trying to delete the 0th position in
// //data while never removing an element (you are trying to delete deleted memory)
// while (!data.empty())
// {
// delete data.at(0);
// }
return 0;
}
Either use a vector of smart pointers like this:
vector<shared_ptr<Item> > myVect;
Or use the Pointer Containers library in boost.
There may be a way to do this and re-use things, but it seems error-prone and a lot more work, especially considering Pointer Containers in boost is a header-only library.
use boost::shared_ptr<Item> and they will be deleted when the vector is cleared, or the element is deleted.
What do I do?
Don't maintain a vector of pointers. Really, it's almost always a mistake and you are fighting against the design of the vector (RAII) which takes care of memory management for you. You now have to call delete on every pointer.
Do you really need a vector of pointers? If you really do (not just think you do, but it is actually a requirement for one reason or another), then use smart pointers.
The vector will dynamically allocate memory for you, just use it as it was intended to be used.
It sounds as if you have the same pointer(s) repeated in your vector. To be sure you are only deleting them once just transfer them to a std::set and delete them there. For example,
std::set<Item*> s( items.begin(), items.end() );
items.clear();
while ( !s.empty() )
{
delete *s.begin();
s.erase( s.begin() );
}
Well, I did it. After a lot of time, a lot of aspirin, and a lot of lost hair, I finally figured out what the problem was. Turns out that I was calling a particular destructor earlier that contained the class which contained this vector of pointers. I had no idea that just calling a destructor would cause it to wipe all static data members. I hate c++ sometimes.
I want to implement an array that can increment as new values are added. Just like in Java. I don't have any idea of how to do this. Can anyone give me a way ?
This is done for learning purposes, thus I cannot use std::vector.
Here's a starting point: you only need three variables, nelems, capacity and a pointer to the actual array. So, your class would start off as
class dyn_array
{
T *data;
size_t nelems, capacity;
};
where T is the type of data you want to store; for extra credit, make this a template class. Now implement the algorithms discussed in your textbook or on the Wikipedia page on dynamic arrays.
Note that the new/delete allocation mechanism does not support growing an array like C's realloc does, so you'll actually be moving data's contents around when growing the capacity.
I would like to take the opportunity to interest you in an interesting but somewhat difficult topic: exceptions.
If you start allocating memory yourself and subsequently playing with raw pointers, you will find yourself in the difficult position of avoiding memory leaks.
Even if you are entrusting the book-keeping of the memory to a right class (say std::unique_ptr<char[]>), you still have to ensure that operations that change the object leave it in a consistent state should they fail.
For example, here is a simple class with an incorrect resize method (which is at the heart of most code):
template <typename T>
class DynamicArray {
public:
// Constructor
DynamicArray(): size(0), capacity(0), buffer(0) {}
// Destructor
~DynamicArray() {
if (buffer == 0) { return; }
for(size_t i = 0; i != size; ++i) {
T* t = buffer + i;
t->~T();
}
free(buffer); // using delete[] would require all objects to be built
}
private:
size_t size;
size_t capacity;
T* buffer;
};
Okay, so that's the easy part (although already a bit tricky).
Now, how do you push a new element at the end ?
template <typename T>
void DynamicArray<T>::resize(size_t n) {
// The *easy* case
if (n <= size) {
for (; n < size; ++n) {
(buffer + n)->~T();
}
size = n;
return;
}
// The *hard* case
// new size
size_t const oldsize = size;
size = n;
// new capacity
if (capacity == 0) { capacity = 1; }
while (capacity < n) { capacity *= 2; }
// new buffer (copied)
try {
T* newbuffer = (T*)malloc(capacity*sizeof(T));
// copy
for (size_t i = 0; i != oldsize; ++i) {
new (newbuffer + i) T(*(buffer + i));
}
free(buffer)
buffer = newbuffer;
} catch(...) {
free(newbuffer);
throw;
}
}
Feels right no ?
I mean, we even take care of a possible exception raised by T's copy constructor! yeah!
Do note the subtle issue we have though: if an exception is thrown, we have changed the size and capacity members but still have the old buffer.
The fix is obvious, of course: we should first change the buffer, and then the size and capacity. Of course...
But it is "difficult" to get it right.
I would recommend using an alternative approach: create an immutable array class (the capacity should be immutable, not the rest), and implement an exception-less swap method.
Then, you'll be able to implement the "transaction-like" semantics much more easily.
An array which grows dynamically as we add elements are called dynamic array, growable array, and here is a complete implementation of a dynamic array .
In C and C++ array notation is basically just short hand pointer maths.
So in this example.
int fib [] = { 1, 1, 2, 3, 5, 8, 13};
This:
int position5 = fib[5];
Is the same thing as saying this:
int position5 = int(char*(fib)) + (5 * sizeof(int));
So basically arrays are just pointers.
So if you want to auto allocate you will need to write some wrapper functions to call malloc() or new, ( C and C++ respectively).
Although you might find vectors are what you are looking for...
I am writing a C++ class that uses some fixed arrays, as well as some dynamically allocated arrays.
I was wondering if anybody can guide me for the proper way to allocate memory for the dynamic arrays , probably in the constructor/deconstructor, and also if I need to explicitly call them to make sure I don't get a seg fault.
Here is a simplified version of the related part of my code:
class Network {
public:
int n_nodes;
int user_index[MAX_USERS]; //a fixed array
int adjacency_matrix[][MAX_ITEMS];
//Network(int n_node, int** adjacency); //I would rather to set the element s in a function other than the constructor
Initializer(int n_node, int** adjacency);
~Netowrk();
}
So here are my specific question for this class:
1 - Can I have the 2D array adjacency_matrix[][] with undecided number of rows and columns until it's set by the user in the initializer function?
2 - where should I delete the 2D array? should I write it in the deconstructor? Should I call the deconstructor explicitly? Is there anything else I need to destroy in the deconstructor?
1 - Can I have the 2D array adjacency_matrix[][] with undecided number of rows and columns until it's set by the user in the initializer function?
Yes. The best way to do this, however, is not to use arrays at all. Instead, use std::vector, which manages the memory for you. There are two ways that you can do this. If you actually want to be able to use the [row][column] syntax to access elements, you'll need to use two dimensions of std::vectors:
std::vector<std::vector<int> > adjacency_matrix;
Once you know the dimensions, you can populate it:
adjacency_matrix.assign(rows, std::vector<int>(columns));
It is often easier to use a single-dimensional array (or a std::vector<int>) containing all of the elements and use row * row_count + column to access the element at index (row, column). This way, there are fewer dynamic allocations. You can wrap up the logic of accessing elements into a couple of helper functions.
2 - where should I delete the 2D array? should I write it in the deconstructor?
You don't have to delete anything if you use a std::vector. It cleans itself up.
Should I call the [destructor] explicitly?
No.
Is there anything else I need to destroy in the [destructor]?
Ideally, no. If you use the Standard Library containers, like std::vector and smart pointers, you shouldn't have to clean anything up. You should avoid trying to manage resources on your own in C++: there are library facilities to do this tedious task for you and you should take advantage of them.
1 - Can I have the 2D array adjacency_matrix[][] with undecided number of rows and columns until it's set by the user in the initializer function?
Yes you can. For example:
int* adjacency_matrix_;
int* getAdjacency(int i, int j)
{
if (!adjacency_matrix_)
return 0;
else
return adjacency_matrix_ + i*n_nodes + j;
}
Network()
: n_nodes(0),
adjacency_matrix_(0)
{}
void Initializer(int n_node, int** adjacency)
{
adjacency_matrix_ = new int[n_nodes * n_nodes];
// Copy over data.
}
As to whether you should, that depends on whether you have a reason for not using std::vector<>.
2 - where should I delete the 2D array? should I write it in the deconstructor?
Should I call the deconstructor explicitly?
Is there anything else I need to destroy in the deconstructor?
Yes, definitely free in the destructor using array operator delete:
~Network()
{
delete [] adjacency_matrix_;
}
No, your destructor will be called whenever the Network object itself goes out of scope. It is (very) rarely necessary to make an explicit destructor call.
No, all a destructor needs to explicitly release is whatever your explicitly acquire.
You may like the example matrix class I wrote in an answer to another question
The question itself was about good C++ design practices, but the chosen example was a multi-dimensional array.
There are several ways to do this.
The easiest way is to use vectors, and if you don't like to manage your own memory, this is perfect for you. However, because I like to manage my own memory, and I have found this method to be slow and cumbersome at times, I have learned of other ways.
The fastest way is to allocated a one dimensional array and treat it as you would a two dimensional array. Here is an example:
int *array = new int[width*height];
int get_array(int column, int row)
{
return array[row*width + column];
}
delete [] array;
This can be generalized to the nth-dimension:
int *array = new int[w1*w2*...*wn];
int get_array(int i1, int i2, ..., int in)
{
return array[in*(w1*w2*...*w(n-1)) + i(n-1)*(w1*w2*...*w(n-2)) + ... + i2*w1 + i1];
}
delete [] array;
If you want to be able to have different widths for each row, then you can make an array of pointers. This solution is slow to initialize and clean up, but flexible, tunable, and has relatively fast execution time. It can also be extremely dangerous if you make a mistake though.
int **array = new int*[height];
for (int i = 0; i < height; i++)
array[i] = new int[width(i)];
at which point, to access it, all you have to do is the customary
array[i][j]
however, to free this array you have to do it row by row
for (int i = 0; i < height; i++)
delete [] array[i];
delete [] array;
This can also generalize to the nth dimension.
int **....*array = new int**...*[w1];
for (int i1 = 0; i1 < w1; i1++)
{
array[i1] = new int**..*[w2];
for (int i2 = 0; i2 < w2; i2++)
{
array[i1][i2] = new int**.*[w3];
...
for (int in = 0; in < wn; in++)
array[i1][i2]...[in] = new int[wn];
}
}
for (int i1 = 0; i1 < w1; i1++)
{
for (int i2 = 0; i2 < w2; i2++)
{
...
for (int in = 0; in < wn; in++)
delete [] array[i1][i2]...[in];
...
delete [] array[i1][i2];
}
delete [] array[i1];
}
delete [] array;
This kind of setup tends to wreak havoc on memory. Just a two dimensional array of these would result in width+1 separate arrays to be malloc-ed. It would be faster to just malloc one big array and figure out the indices yourself.
I wrote a program, which computes the flow shop scheduling problem.
I need help with optimizing the slowest parts of my program:
Firstly there is array 2D array allocation:
this->_perm = new Chromosome*[f];
//... for (...)
this->_perm[i] = new Chromosome[fM1];
It works just fine, but a problem occurs, when I try to delete array:
delete [] _perm[i];
It takes extremely long to execute line above. Chromosome is array of about 300k elements - allocating it takes less than a second but deleting takes far more than a minute.
I would appreciate any suggestions of improving delete part.
On a general note, you should never manually manage memory in C++. This will lead to leaks, double-deletions and all kinds of nasty inconveniences. Use proper resource-handling classes for this. For example, std::vector is what you should use for managing a dynamically allocated array.
To get back to your problem at hand, you first need to know what delete [] _perm[i] does: It calls the destructor for every Chromosome object in that array and then frees the memory. Now you do this in a loop, which means this will call all Chromosome destructors and perform f deallocations. As was already mentioned in a comment to your question, it is very likely that the Chromosome destructor is the actual culprit. Try to investigate that.
You can, however, change your memory handling to improve the speed of allocation and deallocation. As Nawaz has shown, you could allocate one big chunk of memory and use that. I'd use a std::vector for a buffer:
void f(std::size_t row, std::size_t col)
{
int sizeMemory = sizeof(Chromosome) * row * col;
std::vector<unsigned char> buffer(sizeMemory); //allocation of memory at once!
vector<Chromosome*> chromosomes(row);
// use algorithm as shown by Nawaz
std::size_t j = 0 ;
for(std::size_t i = 0 ; i < row ; i++ )
{
//...
}
make_baby(chromosomes); //use chromosomes
in_place_destruct(chromosomes.begin(), chromosomes.end());
// automatic freeing of memory holding pointers in chromosomes
// automatic freeing of buffer memory
}
template< typename InpIt >
void in_place_destruct(InpIt begin, InpIt end)
{
typedef std::iterator_traits<InpIt>::value_type value_type; // to call dtor
while(begin != end)
(begin++)->~value_type(); // call dtor
}
However, despite handling all memory through std::vector this still is not fully exception-safe, as it needs to call the Chromosome destructors explicitly. (If make_baby() throws an exception, the function f() will be aborted early. While the destructors of the vectors will delete their content, one only contains pointers, and the other treats its content as raw memory. No guard is watching over the actual objects created in that raw memory.)
The best solution I can see is to use a one-dimensional arrays wrapped in a class that allows two-dimensional access to the elements in that array. (Memory is one-dimensional, after all, on current hardware, so the system is already doing this.) Here's a sketch of that:
class chromosome_matrix {
public:
chromosome_matrix(std::size_t row, std::size_t col)
: row_(row), col_(col), data_(row*col)
{
// data_ contains row*col constructed Chromosome objects
}
// note needed, compiler generated dtor will do the right thing
//~chromosome_matrix()
// these rely on pointer arithmetic to access a column
Chromosome* operator[](std::size_t row) {return &data_[row*col_];}
const Chromosome* operator[](std::size_t row) const {return &data_[row*col_];}
private:
std::size_t row_;
std::size_t col_;
std::vector<chromosomes> data_
};
void f(std::size_t row, std::size_t col)
{
chromosome_matrix cm(row, col);
Chromosome* column = ch[0]; // get a whole column
Chromosome& chromosome1 = column[0]; // get one object
Chromosome& chromosome2 = cm[1][2]; // access object directly
// make baby
}
check your destructors.
If you were allocating a built-in type (eg an int) then allocating 300,000 of them would be more expensive than the corresponding delete. But that's a relative term, 300k allocated in a single block is pretty fast.
As you're allocating 300k Chromosomes, the allocator has to allocate 300k * sizeof the Chromosome object, and as you say its fast - I can't see it doing much beside just that (ie the constructor calls are optimised into nothingness)
However, when you come to delete, it not only frees up all that memory, but it also calls the destructor for each object, and if its slow, I would guess that the destructor for each object takes a small, but noticeable, time when you have 300k of them.
I would suggest you to use placement new. The allocation and deallocation can be done just in one statement each!
int sizeMemory = sizeof(Chromosome) * row * col;
char* buffer = new char[sizeMemory]; //allocation of memory at once!
vector<Chromosome*> chromosomes;
chromosomes.reserve(row);
int j = 0 ;
for(int i = 0 ; i < row ; i++ )
{
//only construction of object. No allocation!
Chromosome *pChromosome = new (&buffer[j]) Chromosome[col];
chromosomes.push_back(pChromosome);
j = j+ sizeof(Chromosome) * col;
}
for(int i = 0 ; i < row ; i++ )
{
for(int j = 0 ; j < col ; j++ )
{
//only destruction of object. No deallocation!
chromosomes[i][j].~Chromosome();
}
}
delete [] buffer; //actual deallocation of memory at once!
std::vector can help.
Special memory allocators too.