I have a grid class as follows. Using it in my program works fine until the main() function returns then there is an error message and the program crashes due to an uncaught exception. If I comment out the destructor the class works just fine. What would be the correct way to implement this destructor?
If I just delete[] grid I assume that the arrays within it are not deallocated.
Exact error: Unhandled exception at 0x000869F5 in Battleship.exe: 0xC0000005: Access violation writing location 0xDDDDDDDD.
class Grid
{
private:
int numRows;
int numCols;
char** grid; // array of arrays / pointer to pointer to char
public:
/*****************************************************************
Constructor()
*****************************************************************/
Grid() : numRows(0), numCols(0)
{
}
/*****************************************************************
Constructor(int, int)
*****************************************************************/
Grid(int numRows, int numCols) : numRows(numRows), numCols(numCols)
{
grid = new char*[numRows];
for (int arr = 0; arr < numRows; ++arr) {
grid[arr] = new char[numCols];
}
}
/*****************************************************************
Destructor NEEDS MAJOR EDIT AS IT IS CAUSING THE PROGRAM TO CRASH
*****************************************************************/
~Grid()
{
for (int i = 0; i < numRows; ++i)
{
delete[] grid[i]; //delete all subarrays of grid
}
delete[] grid; //delete grid
}
}
Related
I have currently a problem with the following C++ class, which holds the model logic of a cube. The constructor creates a dynamic 2d char array with the following content:
[ [0,0,0,0,0,0],
[1,1,1,1,1,1],
[2,2,2,2,2,2],
[3,3,3,3,3,3],
[4,4,4,4,4,4],
[5,5,5,5,5,5] ].
CubeModel.h
#ifndef CUBEMODEL_H_INCLUDED
#define CUBEMODEL_H_INCLUDED
#include <iostream>
class CubeModel
{
private:
const unsigned short m_faces;
const unsigned short m_fields;
char **m_cube_base_pointer;
public:
CubeModel(const unsigned short faces, const unsigned short fields);
~CubeModel();
void output();
};
#endif // CUBEMODEL_H_INCLUDED
CubeModel.cpp
#include "CubeModel.h"
CubeModel::CubeModel(const unsigned short faces, const unsigned short fields): m_faces(faces), m_fields(fields) {
m_cube_base_pointer = new char*[m_faces];
for (unsigned int i = 0; i < m_faces; ++i) {
m_cube_base_pointer[i] = new char[m_fields * m_fields];
memset(m_cube_base_pointer[i], i, sizeof m_cube_base_pointer[i]);
}
}
CubeModel::~CubeModel() {
for (unsigned int i = 0; i < m_faces; ++i) {
std::cout << (int) m_cube_base_pointer[i][0];
delete [] m_cube_base_pointer[i];
}
delete [] m_cube_base_pointer;
}
/*
Console output of the cube model
*/
void CubeModel::output() {
for (unsigned int i = 0; i < m_faces; ++i) {
for (unsigned int j = 0; j < m_fields * m_fields; ++j) {
std::cout << (int) m_cube_base_pointer[i][j] << std::endl; // output the model
}
}
}
main.cpp
#include <iostream>
#include "CubeModel.h"
using namespace std;
int main() {
CubeModel cube = CubeModel(6, 3);
cube.output();
system("PAUSE");
return 0;
}
When I create a CubeModel object in the main function and call the output method, I got the following error message in Visual Studio:
Exception raised at 0x00FC1DC8 in Cube.exe: 0xC0000005: Access violation at reading a position 0x00000000.
The exception is raised inside the output() method in CubeModel.
What I'm doing wrong here?
The third argument of memset is the number of bytes you want to set.
However
sizeof m_cube_base_pointer[i]
will give you the size of the pointer, not the size of the dynamic array you just allocated. So in order to get the right number of bytes you want to set, you should do
sizeof(char) * m_fields * m_fields
instead. And your memset call should become this:
memset(m_cube_base_pointer[i], i, sizeof(char) * m_fields * m_fields);
I'm having an issue with a lot of memory leaks from a class I've created. The assignment is requires creating a word search puzzle on the heap. I've created my destructor, copy constructor and overload the assignment operator.
I think there must be something wrong with one of these functions, because the final check to ensure it is working is to create objects in a loop, to see if it fails and my function is crashing. I've tried different forms of the destructor and I've tried changing around the copy and assignment operator with no luck. Kind of at a loss, and the lack of warnings is really making it difficult to debug without a proper understanding of the heap.
Any help would be really appreciated!
Here are some functions that are working with the heap.
JumblePuzzle::~JumblePuzzle(){
for (int i = 0; i < size; ++i){
delete jumble[i];
}
delete jumble;
}
JumblePuzzle::JumblePuzzle(string word, string diff){
int i = 0;
toHide = word;
difficulty = diff;
jumble = buildArray();
fillArray();
hideWord();
}
JumblePuzzle::JumblePuzzle(JumblePuzzle& temp){
size = temp.size;
rowPos = temp.rowPos;
colPos = temp.colPos;
direction = temp.direction;
toHide = temp.toHide;
difficulty = temp.difficulty;
jumble = temp.getJumble();
}
JumblePuzzle& JumblePuzzle::operator=(const JumblePuzzle& right){
if (this != &right){
for (int i = 0; i < size; ++i){
delete jumble[i];
}
delete[] jumble;
size = right.size;
rowPos = right.rowPos;
colPos = right.colPos;
direction = right.direction;
toHide = right.toHide;
difficulty = right.difficulty;
jumble = right.getJumble();
}
return *this;
}
charArrayPtr* JumblePuzzle::buildArray() const{
charArrayPtr* array = new char*[size];
for (int i = 0; i < size; ++i){
array[i] = new char[size];
}
return array;
}
Here's the line its failing on.
int loopLimit =20;
for (int i = 0; i < loopLimit; i++)
JumblePuzzle jp("HIDDENWORD", "hard");
Thanks for any possible help!
EDIT:
Here is my .h file as well.
#ifndef JUMBLE_H_
#define JUMBLE_H_
#include <time.h>
#include <cstdlib>
#include <string>
using namespace std;
typedef char* charArrayPtr;
class BadJumbleException {
public:
BadJumbleException(const string&);
string& what();
private:
string message;
};
class JumblePuzzle{
public:
JumblePuzzle(string, string); //simple constructor
JumblePuzzle(JumblePuzzle&); //copy constructor
~JumblePuzzle(); //deconstructor
charArrayPtr* getJumble() const;
JumblePuzzle& operator=(const JumblePuzzle&);
//accessors
int getSize();
int getRowPos();
int getColPos();
char getDirection();
private:
//attributes
int size;
int rowPos;
int colPos;
char direction;
charArrayPtr* jumble;
string toHide;
string difficulty;
void fillArray();
void hideWord();
char randomDirection();
int randomNum(int);
charArrayPtr* buildArray() const;
};
#endif
and my getJumble. It's used to get the actual word search created. Returned a copy rather than the pointer so it cant be modified.
charArrayPtr* JumblePuzzle::getJumble() const{
charArrayPtr* tempJumble = new char*[size];
for (int i = 0; i < size; ++i){
tempJumble[i] = new char[size];
}
for (int i = 0; i < size; i++){
for (int j = 0; j < size; j++){
tempJumble[i][j] = jumble[i][j];
}
}
return tempJumble;
}
There is one major thing wrong with your code, and that is you failed to initialize the "size" member in the JumblePuzzle(string, string) constructor.
There are other things you should do:
1) Create a separate function to destroy the 2d array within the JumblePuzzle class. You seem to be copying the same loops to do this in multiple places. No need for that if you just call a function to do this work.
2) Your assignment and copy constructor are not exception safe. If new[] throws an exception during the creation of the copy, then the original object has invalidated data. In other words, you've destroyed the data, and when you want to create another 2d array, when new[] says "oops", you've destroyed your original data and can't get it back.
This code works fine in VS2010 but now I am trying to port it to my mac with xcode 4.6 and it's giving me some bad access errors at run time. Basically I have a board class which contains a 2d array of tiles, when I create the board I can access the tiles functions but when I later run my draw function it gives me bad access. Here is a sample of my board class.
Board.h
#include "Tile.h"
class Board
{
private:
//This is the GameBoard of a 2D array of Tiles
Tile *** GameBoard;
void CreateBoard(const int size);
void FillValues();
...
public:
Board(int size);
void DrawBoard();
...
}
Board.cpp
Board::Board(const int size)
{
won=false;
lost=false;
BoardSize =size;
GameBoard = new Tile**[size];
CreateBoard(size);
}
void Board::CreateBoard(const int size)
{
...
FillValues()
}
void Board::FillValues()
{
for(int x=1;x<BoardSize+1;x++)
{
for(int y =1;y<BoardSize+1;y++)
{
if (GameBoard[x][y]->Type()=="NumberTile")
{
int neighbors = CountNeighbours(x,y);
GameBoard[x][y]->SetValue(neighbors);
//This works
}
}
}
}
void Board::DrawBoard()
{
for(int i=0;i<=BoardSize+1;i++)
{
for (int j=0;j<=BoardSize+1;j++)
{
if (GameBoard[i][j]->Type() != "BorderTile") {
GameBoard[i][j]->Draw();
//This does not work, i get the error when it tries to use ->Type()
}
}
}
}
...
I call the functions like this
GI = new Board(SCREEN_SIZE);
GI->DrawBoard();
GameBoard = new Tile**[size];
This just creates an array of Tile**. You don't yet have any actual Tiles or even Tile*s and later, when you're trying to access elements of the array with GameBoard[x][y]->, you're hitting undefined behaviour.
As you have it, you would need to do this:
GameBoard = new Tile**[size]; // Allocate an array of Tile**
for (int i = 0; i < size; i++) {
GameBoard[i] = new Tile*[size]; // Allocate an array of Tile*
for (int j = 0; i < size; j++) {
GameBoard[i][j] = new Tile(); // Allocate an array of Tile
}
}
However, this is awful. It's three lots of dynamic allocation that you have to remember to tidy up at the end (and tidy up correctly).
A simpler approach would be to just have an 2D array of tiles:
Tile GameBoard[CONSTEXPR_SIZE][CONSTEXPR_SIZE];
Or better yet, use the std::array container:
std::array<std::array<Tile, CONSTEXPR_SIZE>, CONSTEXPR_SIZE> GameBoard;
Here, the size given has to be a constant expression. If you need it to be dynamically sized, use a std::vector instead.
In the comments below, you say the size of your array is actually BoardSize+1. Still, you are iterating over too many elements in both your outer and inner for loops:
for(int i=0;i<=BoardSize+1;i++)
This should be:
for(int i=0; i<BoardSize+1; i++)
Also in the comments below, you say that Type returns a char*. That means you can't do your string comparison like this:
GameBoard[i][j]->Type() != "BorderTile"
This simply performs pointer comparison, since the left operand is a char* and the right operand is convertible to const char*. It doesn't compare the strings themselves. Instead, you want:
GameBoard[i][j]->Type() != std::string("BorderTile")
This will force std::string comparison to be used.
Hi I have a problem with deleting an object array.
Whenever I start my code, it works just fine, but when I close,
I am getting the error: 0xC0000005: Access violation reading location 0xcccccccc.
The code goes like this:
I initialize an instance of an object and immediately make an empty array out of it.
Class* classObject[15];
Afterwards, I define the empty array in a for loop.
for(int i = 0; i < 15; i++){
classObject[i] = new Class();
}
When the application closes, the following code should delete the array out of memory.
for(int i = 0; i < 15; i++){
delete classObject[i];
}
Instead of successfully closing, I am getting the Access violation error.
How can I fix this problem and where?
Also, are there maybe other ways I could create objects in a for loop?
class A
{
public:
A():a(0){};
private:
int a;
};
int main()
{
A* arr[15];
for(int i=0;i<15;i++)
{
arr[i] = new A();
}
for(int i =0;i<15;i++)
{
delete arr[i];
}
return 0;
}
There is no any error in my code .Have you delete the point before?
I need a double pointer of type DizzyCreature (my class) to point to an array of DizzyCreature pointers. When I run it I get "Access violation reading location 0x...". I can make a DizzyCreature* and call its member functions just fine, but when cannot run through the array and do the same thing for each obj.
I am following these instructions:
http://www.cplusplus.com/forum/beginner/10377/
Code
Server.h:
class Server
{
public:
Server(int x, int y, int count);
~Server(void);
void tick();
private:
DizzyCreature** dcArrPtr;
DizzyCreature* dcPtr;
int _count;
};
Server.cpp:
Server::Server(int x, int y, int count)
{
dcPtr = new DizzyCreature[count]; // this works just fine
dcArrPtr = new DizzyCreature*[count]; // this doesn't (but gets past this line)
_count = count;
}
Server::~Server(void)
{
delete[] *dcArrPtr;
delete[] dcPtr;
}
void Server::tick()
{
dcPtr->takeTurn(); // just fine
for (int i = 0; i < _count; i++) {
dcArrPtr[i]->takeTurn(); // crash and burn
}
}
EDIT:
The member function takeTurn() is in a parent class of DizzyCreature. The program makes it into the function, but as soon as it attempts to change a private member variable the exception is thrown. If it matters, DizzyCreature is of type GameCreature and WhirlyB as this is an assignment on MI.
You have allocated space for dcArrPtr, but didn't allocate every object in this array. You must do following:
Server::Server(int x, int y, int count)
{
dcPtr = new DizzyCreature[count];
dcArrPtr = new DizzyCreature*[count];
for ( int i = 0; i < count; i++ ) {
dcArrPtr[ i ] = new DizzyCreature;
}
_count = count;
}
Server::~Server(void)
{
for ( int i = 0; i < count; i++ ) {
delete dcArrPtr[ i ];
}
delete[] *dcArrPtr;
delete[] dcPtr;
}
This:
dcPtr = new DizzyCreature[count];
"creates" an array of DizzyCreatures, whereas:
dcArrPtr = new DizzyCreature*[count];
"creates" an array of pointers to DizzyCreatures, but crucially doesn't create instances for those pointers to point to.
The preferred solution is to use a standard container for tasks like this anyway though. If you really want to do it like this (and are aware that it's not best practice to do this manually) then you'll need a loop to call new for eachelement in the array of pointers.
You allocate an array of count pointers instead of an array of count objects.
Instead of
dcArrPtr = new DizzyCreature*[count];
you might want to
dcArrPtr = new DizzyCreature[count];
You're allocating an array of pointers, but those pointers aren't valid until you set them to something.
double **arr = new double*[10];
for(int i=0;i<10;++i) {
arr[i] = new double[10];
}
That said, when starting out with C++ you should probably avoid raw arrays and instead use std::array and std::vector:
class Server
{
public:
Server(int x, int y, int count);
void tick();
private:
std::vector<std::vector<DizzyCreature>> dcArrPtr;
std::vector<DizzyCreature> dcPtr;
};
Server::Server(int x, int y, int count)
{
dcPtr.resize(count);
dcArrPtr.resize(count);
}
void Server::tick()
{
dcPtr[0].takeTurn();
for (int i = 0; i < dcArrPtr.size(); i++) {
dcArrPtr[i][0].takeTurn();
}
}
Use a
std::vector<std::vector<DizzyCreature>>
Furthermore, if you want to use raw pointers (which I do not recommend), you'll have to allocate memory for each pointer in your array.
class A
{
std::vector<std::vector<int>> v_;
public:
A()
: v_(500, std::vector<int>(500))
{} // 500 x 500
};
class B
{
int** v_;
public:
B()
: v_(new int*[500])
{ // not even exception safe
for (int i = 500; i--; )
v_[i] = new int[500];
}
~B()
{
for (int i = 500; i--; )
delete[] v_[i];
delete[] v_;
}
};
If you would have seen the implementation of dynamic memory allocation of 2-Dimensional array . That would have given you a better insight of how to proceed in such cases . Most of the answers has already answered you what to do . But just go through any link and see how is memory allocated in case of 2-D array . That Will also help you .