This is the code.
message Bar {}
int vec_size = 100;
std::vector<Bar*> vec;
vec.reverse(vec_size);
for (int i = 0; i < vec_size; i++) {
vec.push_back(new Bar());
}
// other code.
//call some functions;
// I think we need to do this if the vec is no longer used.
for (int i = 0; i < vec_size; i++) {
delete vec[i];
}
As known to all, we need to free memory allocated with new. But I'm not sure whether protobuf message is different from others.
Moreover, is it a good idea if we replace std::vector<Bar*> with std::vector<std::shared_ptr<Bar>>?
Related
I just need to be sure I have enough memory available to the bi-dimensional array map. So I think I'd have to put a try catch bad:alloc in every row of map or perhaps with no throw would be more elegant. But I can't get with it. Any help would be appreciated...
I've read some articles about writing something like:
map[i] = new int [columns];
if (map[i] == NULL)
cout << “No enough memory”;
I don't like this solution and I've read that is not very reliable one.
fillmaze is a function called inside the constructor of maze..
void Maze::setupMaze(int r, int c, int l){
rows = r;
columns = c;
level = l;
fillMaze();
addBorders();
centerWalls();
getaway();
addWalls();
}
void Maze::fillMaze(){
map = new int* [rows];
for (int i = 0; i < rows; i++) {
map[i] = new int[columns];
}
//Inicializamos toda la tabla
for (int i = 0; i < rows; i++) {
for (int j = 0; j < columns; j++) {
map[i][j] = PASSAGE;
}
}
}
Also delete [] map is not enough right ? I'm doing in the destructor of the class:
Maze::~Maze(void)
{
for (int i = 0; i < rows; ++i)
delete[] map[i];
delete[] map;
}
This is why you should use std::vector<> as it will handle all the memory management for you correctly.
Issue 1: new never returns NULL (for pedants the normal new as used below). Also note in C++ we use nullptr not NULL for type safety.
map[i] = new int [columns];
if (map[i] == NULL) // This will never be NULL
cout << “No enough memory”; // So this will never print anything.
If fillmaze() is called from the constructor. Then if it throws an exception your destructor is never called. This means you have to deal with any allocation failure in place.
map = new int* [rows]; // could throw.
for (int i = 0; i < rows; i++) {
map[i] = new int[columns]; // could throw
}
So you have to handle and be able to detect what has been allocated and thus what needs to be dallocated.
try
{
map = nullptr; // Init to nullptr to make sure
// you can distinguish between valid state
// and what could have randomly been in memory.
map = new int* [rows]{nullptr}; // Initialize all elements to nullptr.
// If any throw you don't want your code
// to start releasing random pointers.
// calling delete on nullptr is fine.
for (int i = 0; i < rows; i++) {
map[i] = new int[columns]{PASSAGE};
}
}
catch(...) // catch all exceptions.
{
if (map != nullptr) { // You should only loop over
// map if it has been allocated.
for (int i = 0; i < rows; i++) {
delete [] map[i];
}
}
delete [] map; // delete the map.
throw; // rethrow exception
}
Your destructor is dine.
But you can simplify this by simply using a vector:
std::vector<std::vector<int>> maze{std::vector<int>{PASSAGE, columns}, rows};
//gives the error expecting a declaration
int** my_array;
for (int i=0; i<200; i++)
{
my_array[i]= new int [200];
}
//initialize array with zeroes
for (int i = 0; i<200; i++)
{
for (int j = 0; j<200; j++)
{
my_array[i][j] =0;
}
}
In brief:
The 2D array is declared globally
It is initialized in the main. The main calls a function that saves 0's or 1's in specific cells of the array
The array is then printed by the main
Also advice whether the flow is correct?
If you want an array of an array of 200 bools, you could use std::array and std::bitset.
#include <bitset>
#include <array>
//...
std::array<200, std::bitset<200>> my_array;
Second, your code, even if you fix the syntax error is wrong. You would need to create my_array this way:
int** my_array;
//...
my_array = new int * [200];
for (int i = 0; i < 200; ++i )
my_array[i] = new int [200];
Then somewhere you have to delete this memory:
for (int i = 0; i < 200; ++i )
delete [] my_array[i];
delete [] my_array;
An alternate that creates a contiguous block and uses only two calls to new[]:
my_array = new int * [200];
int *pool = new int [200*200];
for (int i = 0; i < 200; ++i, pool += 200 )
my_array[i] = pool;
Then somewhere you have to delete this memory:
delete [] my_array[0];
delete [] my_array;
However I advise you use a container such as the std::array, std::bitset, std::vector, etc. instead of the int** approach.
Regarding your syntax error, it's probably due to something before the code you have shown.
The shown code,
int** my_array;
for (int i=0; i<200; i++)
{
my_array[i]= new int [200];
}
//initialize array with zeroes
for (int i = 0; i<200; i++)
{
for (int j = 0; j<200; j++)
{
my_array[i][j] =0;
}
}
compiles fine as the body of a function.
Regarding the logic, which is incorrect and which uses troublesome constructs,
do this:
auto my_array = vector<vector<bool>>( 200, vector<bool>( 200 ) );
where vector is std::vector from the <vector> header.
This avoids the raw pointers, the new-ing`, the loops, etc., all that you find problematic.
Alternatively you can declare it like this:
vector<vector<bool>> my_array( 200, vector<bool>( 200 ) );
Note that a global variable is usually troublesome, best avoided.
Sorry to ask for an answer to something so probably simple, but I can't figure this one out by myself, it seems.
So, I have a header file, like so:
#ifndef LEVELMAP_H
#define LEVELMAP_H
#include "Constants.h"
class LevelMap
{
public:
LevelMap(int map[MAP_HEIGHT][MAP_WIDTH]);
~LevelMap();
int GetTileAt(unsigned int h, unsigned int w);
private:
int** mMap;
};
#endif LEVELMAP_H
And a .ccp file like so:
#include "LevelMap.h"
// 0 = empty, 1 = blocked
LevelMap::LevelMap(int map[MAP_HEIGHT][MAP_WIDTH])
{
//Allocate memory for the level map.
mMap = new int*[MAP_HEIGHT];
for(unsigned int i = 0; i < MAP_HEIGHT; i++)
{
mMap[i] = new int[MAP_WIDTH];
}
//Populate the array.
for(unsigned int i = 0; i < MAP_HEIGHT; i++)
{
for(unsigned int j = 0; j < MAP_WIDTH; j++)
{
mMap[i][j] = map[i][j];
}
}
}
LevelMap::~LevelMap()
{
//Delete all elements of the array.
for(unsigned int i = 0; i < MAP_HEIGHT; i++)
{
delete [] mMap[i];
}
delete [] mMap;
}
int LevelMap::GetTileAt(unsigned int h, unsigned int w)
{
if(h < MAP_HEIGHT && w < MAP_WIDTH)
{
return mMap[h][w];
}
return 0;
}
Now, I get an access violation on the 'return mMap[h][w];' line, and I can't for the life of me figure out a solution.
For context, GetTileAt() is being used to detect if a certain tile on the screen should allow the player to collide with it or not.
You are not giving the exact error message that you get, but from the title I deduce that this is what you are looking at:
0xBAADF00D : Used by Microsoft's debug HeapAlloc() to mark uninitialized allocated heap memory
Which in your case would mean that mMap was never created. Try to delete all default constructors to find the exact error causing this. The default move, copy, and empty constructors will not work properly anyways, so it is good practice to delete them!
Okay, so here's the context. I've been up for almost a day straight now working on the legendary 8-puzzle problem. I have my heuristics down and my A_star algorithm down. We are required by the project spec to solve it using three different heuristic values. I can solve it for any one of the three individually, but when I go to solve them in succession, I get a ridiculous loop, and it never finds the correct successor state.
I believe my problem is with my pointers. I have a class, State, as defined below that has an int** array and a pointer to a State (its parent).
EDIT: I have to use int** as defined by the project specification, otherwise I would gladly use a pointer.
State (int **bd, State* prnt);
State (const State& other);
~State ();
I am then declaring them as such:
State::State(int **bd, State* prnt) {
// allocate the board
board = new int*[3];
for (int i = 0; i < 3; i++) {
board[i] = new int[3];
}
// fill in the board
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
board[i][j] = bd[i][j];
//board[i][j] =
}
}
// set the parent
parent = prnt;
}
State::State(const State& other) {
// allocate the board
board = new int*[3];
for (int i = 0; i < 3; i++) {
board[i] = new int[3];
State::~State() {
//std::cout << "Deconstructing " << this << endl;
for (int i = 0; i < 3; i++)
delete board[i];
delete [] board;
delete parent;
parent = other.parent;
}
State::~State() {
//std::cout << "Deconstructing " << this << endl;
for (int i = 0; i < 3; i++)
delete board[i];
delete [] board;
delete parent;
}
State& State::operator=(const State &rhs) {
if (&rhs == this) {
return *this;
}
for (int i = 0; i < 3; i++) {
delete board[i];
}
delete [] board;
// allocate the board
board = new int*[3];
for (int i = 0; i < 3; i++) {
board[i] = new int[3];
}
// fill in the board
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
//board[i][j] = rhs.board[i][j];
board[i][j] = rhs.getIntAtCoor(j, i);
}
}
//delete parent;
// set the parent
parent = rhs.parent;
// set g
g = rhs.g;
f = rhs.f;
hType = rhs.hType;
return *this;
}
I don't give the exact declarations -- some of it is simple like int = int. I just can't quite figure it out. I feel like either my delete parent is wrong or my parent = other.parent is wrong (or both).
Thank you for your time and help,
Tyler
Upgrading your code-style may force the errors to evaporate. In other words new and delete are error prone and should be avoided when better alternative exists.
For management of the cells consider:
std::shared_ptr: can be used to void the delete calls
std::vector can be used to avoid the new and delete calls
Note you should use it like std::vector<int> board( 3 * 3 ) and board.at( x + y * 3 ).
And best of all just use a static array int board[3][3]. No allocation at all.
Also child states do not own their parent states. It's the other way around. So child states shouldn't delete their parents. You can still safely keep a parent pointer, but make sure you cleanup the children before you allow a parent to go out of scope (deleted or otherwise). All of this cleaning and deleting doesn't neccessarily involve new at all. Your State class looks small enough that is doesn't matter if they are copied by value. In which case just have the parent use a std::vector<State> m_children and the compiler will take care of the rest.
You don't show the full definition of the copy constructor but I assume that the parent = other.parent line is in there. In that case, wouldn't the parent be responsible for its own lifetime and the delete parent in the destructor shouldn't exist at all.
Also note that you need to at least disable (private declaration) or implement the copy assignment operator.
Better still, use a vector of vector for your 2d array and let the language work for you.
Perhaps not a direct answer, but you are going against best practices for C++.
It's easier and definitely more maintainable to use vectors for this problem.
size_t row_sz = 3;
size_t col_sz = 3;
std::vector<int> board(row_sz * col_sz, 0);
int i = 0;
for (size_t r = 0; r < 0; r++)
for (size_t c = 0; c < 0; c++)
board[ r * row_sz + c ] = i++;
Multidimensional arrays are much easier handled with the above strategy as well. It just breaks less. If you really want the row/col access, write a wrapper around it.
struct Matrix {
int &operator()(size_t r, size_t c);
const int &operator()(size_t r, size_t c) const;
private:
std::vector<int> data;
};
How do I deallocate this type of 3D array in c++? I have a class that has a int*** volume as a member and I filled it this way..
volume = new int**[xSize];
for(int i =0; i<xSize; i++)
{
volume[i] = new int*[ySize];
for(int j =0; j<ySize; j++)
{
volume[i][j] = new int[zSize];
for(int k = 0; k<zSize;k++)
{
volume[i][j][k] = 0;
}
}
}
You just reverse your actions (other than the filling of the array)
for(int i =0; i<xSize; i++)
{
for(int j =0; j<ySize; j++)
{
delete[] volume[i][j];
}
delete[] volume[i];
}
delete[] volume;
If you can, avoid manual dynamic memory management in the first place. E.g. using std::vector:
typedef std::vector<int> Vec1D;
typedef std::vector<Vec1D> Vec2D;
typedef std::vector<Vec2D> Vec3D;
Vec3D volume(xSize, Vec2D(ySize, Vec1D(zSize, 0)));
As pointed out in the comments, Boost.MultiArray is a convenient alternative.
You need to recursively iterate through all levels of the structure the same way as above (except the innermost level), and delete each element in reverse order compared to their allocation:
for(int i =0; i<xSize; i++)
{
for(int j =0; j<ySize; j++)
{
delete[] volume[i][j];
}
delete[] volume[i];
}
delete[] volume;
In reverse.
You need the same loop structure, but for every new[], you need a delete[] instead, and now nested stuff must occur before outer stuff.
So:
int **x = new int*[M];
for (i = 0; i < M; i++)
{
x[i] = new int[N];
}
becomes:
for (i = 0; i < M; i++)
{
delete [] x[i];
}
delete [] x;
Easy - Just do the steps in reverse
i.e. delete all those volume[i][j] that you have created
Then volume[i] for all i values
Then volume.
It is a bit like losing your keys - you just need to retrace your steps!
The general rule is this: you need to have one matching delete[] for each and every new[]. You seen to have one instance of new int**[], xSize instances of new int*[], and ySize instances of new int[].
So, you might free them all thus:
for(int i =0; i<xSize; i++)
{
for(int j =0; j<ySize; j++)
{
delete[] volume[i][j];
}
delete volume[i];
}
delete[] volume;