Dynamically allocating array of objects - c++

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 .

Related

A shared pointer query from a novice user. I have code below that crashes when using a container of class with member shared pointers

//this is my main Method ,this was an experiment to understand shared pointer usage
#include <iostream>
#include "shared_ptrtestA.h"
int main(int argc, const char * argv[]) {
// declare a shared pointer to the class
sharedptr_testA* A = new sharedptr_testA(5);
//class has a vector , push back a new instance into the vector
A->mvect.push_back(sharedptr_testA::Aptr(new sharedptr_testA::testA(
sharedptr_testA::sharedptr_testB::Create(1) , sharedptr_testA::sharedptr_testC::Create(1)
)));
//class has a vector , push back a new instance into the vector
A->mvect.push_back(sharedptr_testA::Aptr(new sharedptr_testA::testA(
sharedptr_testA::sharedptr_testB::Create(2),sharedptr_testA::sharedptr_testC::Create(2)
)));
//iterate the vector populated above
for(std::vector<sharedptr_testA::Aptr>::iterator it = A->mvect.begin() ;
it!= A->mvect.end() ; it++)
{
// get members from the vector iterator
sharedptr_testA:: sharedptr_testB::Bptr B = (*it)->mb;
sharedptr_testA:: sharedptr_testC::Cptr C = (*it)->mc;
// print contents of members
for(int i = 0 ; i < B->m_size ; i++)
{
std::cout<<B->bytes[i]<<'\t';
}
std::cout <<std::endl;
for(int i = 0 ; i < C->m_size ; i++)
{
std::cout<<C->bytes[i]<<'\t';
}
std::cout <<std::endl;
}
}
//this was the main method above and the expected output was
B
C
BB
CC
The structure of the classes used are
//Header File
#ifndef shared_ptrtest_shared_ptrtestA_h
#define shared_ptrtest_shared_ptrtestA_h
#include <memory>
#include <functional>
#include <vector>
class sharedptr_testA
{
public:
// constructor and destructor
sharedptr_testA(int vsize);
~sharedptr_testA();
// an internal class member defined
class sharedptr_testB
{
public:
typedef std::shared_ptr<sharedptr_testB> Bptr;
//static create method
static Bptr Create(int msize)
{
return Bptr(new sharedptr_testB(msize));
}
//members
int m_size;
char *bytes;
//private contructor
private:
sharedptr_testB(int size)
{
m_size = size;
bytes = new char[size];
for(int i = 0 ; i < size ; i++)
bytes[size]= 'B';
}
};
//class c has same structure as class B above
class sharedptr_testC
{
public:
typedef std::shared_ptr<sharedptr_testC> Cptr;
static Cptr Create(int msize)
{
return Cptr(new sharedptr_testC(msize));
}
int m_size;
char *bytes;
private:
sharedptr_testC(int size)
{
m_size = size;
bytes = new char[size];
for(int i = 0 ; i < size ; i++)
bytes[size]= 'C';
}
};
// struct containing shared pointers to classes defined above
struct testA
{
testA(sharedptr_testB::Bptr B, sharedptr_testC::Cptr C)
{
mb = B;
mc = C;
}
sharedptr_testB::Bptr mb;
sharedptr_testC::Cptr mc;
};
typedef std::shared_ptr<testA> Aptr;
std::vector<Aptr> mvect;
};
#endif
//The short cpp file for the above class contains only constructor and destructor
#include "shared_ptrtestA.h"
sharedptr_testA::sharedptr_testA(int vsize)
:mvect(vsize)
{
}
sharedptr_testA::~sharedptr_testA()
{
}
What is wrong in the above code ? I wrote this to understand shared pointer usage
You have two bugs in your program:
The loops in constructors of sharedptr_testB and sharedptr_testC use size instead of i for indexing. It should be:
sharedptr_testB(int size)
{
m_size = size;
bytes = new char[size];
for(int i = 0 ; i < size ; i++)
bytes[i]= 'B';
}
(DTTO) for sharedptr_testC)
You start with a vector of size 5, which means it stores five null pointers. Then you append two elements to it (size 7, five nulls + two valid pointers). The you iterate over it, dereferencing each pointer. This of course crashes, since there are nulls at the beginning. Simply initialise the vector as empty.
sharedptr_testA* A = new sharedptr_testA(0);
With these two fixes, the code works.
Side notes 1 (C++):
The code is next to impossible to read. I strongly suggest you use a better naming scheme.
sharedptr_testB and sharedptr_testC leak memory. I understand it's just a learning excercise, I'd just like to point it out. You'd be better off with std::vector<char> in them instead of char*.
Side notes 2 (Stack Overflow):
If you have a crashing program, you should generally try to debug it yourself before asking an SO question. Stepping through the program through a debugger would easily have uncovered both the issues.

How can I do to get correct output in class?

This is the default constructor with no parameters. By default, this allocates space for a
double array of size 10 and assigns a default value of 0 to each of them.
its a ""class"" , I m not sure what i m doing right or wrong..
I fill the public body functions , but my output is nothing suppose to print 0000000000
, I m very new to coding.
class DataVector
{
private:
DataType *m_data;//Pointer to dynamically allocated memory that holds all items
UIntType m_size;//Size of the m_data array
public:
DataVector()
{
double *m_data = new double[m_size];
for (int i = 0; i < m_size; i++)
{
*m_data = 0;
m_data++;
}
}
void PrintItems()
{
for (int i = 0; i < m_size; i++)
{
cout << *m_data << " ";
m_data++;
}
}
};
void TestDataVector()
{
{
DataVector d1;
d1.PrintItems();
}
}
There are a few problems with this implementation of yours:
You are not initializing m_size
You change the value of the pointer m_data which is supposed to hold the address of first member of the array. So, at the end of the initializer, m_data is pointing to a spot one after the block you had allocated by new.
same in the printItems member function, but here the pointer already points to an invalid location.
Also, because you are allocating memory in the constructor, you should also define a destructor to free that memory.

Memory leaks passing dynamic variables recursively

I have a recursive function that requires me to create a new array every time the function is called. The function also requires the array that was previously created:
void myFunc(int* prevArray)
{
int newSize;
//do some calculations to find newSize
int* newArray;
newArray = new int[newSize];
//do some calculations to fill newArray
//check some stopping condition
myFunc(newArray);
}
This function leaks memory, but I can't avoid that by adding
delete[] newArray;
since I can only add that after calling the function again. How can I solve this?
You can solve this by making use of dynamic memory allocation.
// allocate initial size
const int INITIAL_SIZE = 5;
int *myArray = malloc(sizeof(int) * INITIAL_SIZE));
int myFunc(int *aArray, int numAllocated) {
int numElements = calculateNewSize();
if (numElements != numAllocated) {
// allocate new size
realloc(aArray, (numElements * sizeof(int));
}
return numElements;
}
Now you can call myFunc like this:
int numElements;
numElements = myFunc(myArray, numElements);
When your done using myFunc don't forget to free the memory
free(myArray);
Try something like
void myFunc(int* prevArray)
{
int newSize;
...newArray = new int[newSize];
myFunc(newArray);
delete[] newArray;
}
or better yet use std::unique_ptr to control the newArray memory. In this way you will follow the rule of thumb regarding dynamic memory - that it should have one owner, responsible for both allocating and freeing it.
You might just use a vector and swap the new result into the final result.
#include <iostream>
#include <vector>
struct X { ~X() { std::cout << "Destruction\n"; } };
void recursive(unsigned n, std::vector<X>& result) {
// Put new_result in a scope for destruction
{
std::vector<X> new_result(1);
// Do something
// The previous result is no longer needed
std::swap(result, new_result);
}
// Next recursion
if(n) {
std::cout << "Call\n";
recursive(--n, result);
}
}
int main() {
std::vector<X> result(1);
std::cout << "Call\n";
recursive(3, result);
return 0;
}

Access pointer array / through another pointer and delete single element in array without deleting first pointer or whole array

In my Main Window I create an instance of PointerClass, which holds an array of pointers to PointerObject (I want to be able to access it with PointerObject[X][Y] and delete it the same way, and check if PointerObject[X][Y] == NULL (which is WHY I use pointers)) and I don't want a solution with vectors.
#define X 10
#define Y 10
class PointerObject
{
public:
int X;
int Y;
}
class PointerClass
{
public:
PointerObject *ArrayOfPointerObjects[X][Y];
}
PointerMethod(&PointerClass);
Then, in my PointerMethod I create the Pointer to an array:
PointerMethod(PointerClass *pointerClass)
{
// don't know the right way to do this
pointerClass->ArrayOfPointerObjects= new PointerObject[X][Y];
// set all pointers in the array to NULL - is this needed?
for (int x=0; x < X; x++)
{
for (int y=0; y < Y; y++)
{
pointerClass->ArrayOfPointerObjects[x][y] = NULL;
}
}
// trying to store some data here
pointerClass->ArrayOfPointerObjects[0][0] = new PointerObject;
// trying to delete it
delete pointerClass->ArrayOfPointerObjects[0][0];
// or trying this:
delete[] pointerClass->ArrayOfPointerObjects[0][0];
// causes access violation or doesn't work
}
I earlier asked this without success or questions about the wrong type.
Delete pointer to multidimensional array in class through another pointer - how?
I can access the array, check if it's NULL. but when I call delete / delete[] pointerClass->ArrayOfPointerObjects[x][y] it seem to delete the pointer to pointerClass instead of the element at [X][Y] and I want to delete the pointer at location [X][Y] and not the pointerClass and I don't want to delete the whole array.
How can I do this without complicating it too much? I guess my array isn't truely an array of pointers, just a pointer to an array. But I want it to be an array of pointers stored in a pointer or something. Still the importance is how I access it and how I delete the elements in the array. I need to be able to check if the pointer is NULL and if not be able to Delete that single PointerObject.
The importance of this is that I want to:
Access the array of PointerObjects with [X][Y]
Check if an object in the array is NULL (=needs pointers)
Delete a single item in the array of pointers without destroying the pointer to the PointerClass object or deleting the rest of the array. Just delete a single PointerObject at a certain X, Y location in the array so that [X][Y] after deletion = NULL.
If there's too much confusion or likeness with my other thread it is because people told me thing I had no wish for and it led off subject, here it is better illustrated how it works and how I want it to work like.
hmm, i think something like this
#include <iostream>
class Foo
{
int i_;
int j_;
public:
Foo(int i, int j) : i_(i), j_(j) {}
void print_coords()
{
std::cout << this << " (" << i_ << ',' << j_ << ')' << std::endl;
}
};
class Bar
{
public:
Foo *arr[5][5];
};
class Que
{
public:
void init(Bar *b)
{
for(int i=0; i<5; i++)
for(int j=0; j<5; j++)
b->arr[i][j] = new Foo(i, j);
}
void print(Bar *b, int i, int j)
{
try {
if(b->arr[i][j])
b->arr[i][j]->print_coords();
else
throw 0;
} catch (int e) {
std::cout << &b->arr[i][j] << " points to null" << std::endl;
}
}
void rem(Bar *b, int i, int j)
{
delete b->arr[i][j];
b->arr[i][j] = 0;
}
};
int main()
{
Bar *b = new Bar();
Que *q = new Que();
q->init(b);
q->print(b, 2, 2);
q->rem(b, 2, 2);
q->print(b, 2, 2);
return 0;
}

What's the proper way to pass a pointer to a function for deletion?

I have a matrix declared like int **matrix, and I know that the proper way to pass it to a function to allocate memory should be like this:
void AllocMat(int ***mat, int size);
But now I need to delete these memory in another function and am not sure about what to pass:
void DeallocMat(int **mat, int size);
or
void DeallocMat(int ***mat, int size);
I think the second one should be right, but neither way gives me segmentation fault as I tried.
The question is tagged C++, and yet the answers only use the C subset...
Well, first of all, I would recommend against the whole thing. Create a class that encapsulates your matrix and allocate it in a single block, offer operator()(int,int) to gain access to the elements...
But back to the problem. In C++ you should use references rather than pointers to allow the function to change the argument, so your original allocate signature should be:
void AllocMat(int **&mat, int size);
And call it like:
int **matrix = 0;
AllocMat( matrix, 5 );
Or better, just return the pointer:
int **AllocMat( int size );
int **matrix = AllocMat( 5 );
For the deallocation function, since you don't need to modify the outer pointer, you can just use:
void DeallocMat( int**mat, int size ); // size might be required to release the
// internal pointers
Now, for a sketch of the C++ solution:
template <typename T> // no need to limit this to int
class square_matrix {
const unsigned size;
T * data;
public:
square_matrix( unsigned size ) : size(size), data( new T[size*size]() ) {}
square_matrix( matrix const & m ) : size( m.size ), data( new T[m.size*m.size] ) {
std::copy( m.data, m.data+size*size, data );
}
~matrix() {
delete [] data;
}
T const & operator()( unsigned x, unsigned y ) const {
// optional range check and throw exception
return data[ x + y*size ];
}
void set( unsigned x, unsigned y, T const & value ) {
// optional range check and throw exception
data[ x + y*size ] = value;
}
};
First is correct. But your real problem is that you are using pointers when there are better alternatives. For a 2d matrix you should use a vector of vectors
#include <vector>
typedef std::vector<std::vector<int> > Matrix;
Matix m;
Now there is no need to delete anything, so one less thing to go wrong.
void DeallocMat(int **mat, int size) - allows you to deallocate memory (since you have passed the value of mat only allowing to deallocate memory but not change mat)
void DeallocMat(int ***mat, int size) - allows you to deallocate memory and change the value of mat to NULL (since you have now passed a pointer to mat allowing you to change its value)
The extra "*" just handles the pointer to be behaved as call by reference. If you want to get the output from your function, you need an extra "*" in your declaration. In this case, you should pass the reference of your pointer (using &) to these functions.
The reason why you required to pass a pointer to double pointer because your local variable must required to reflect with the new updated memory
void Foo(int * a)
{
a = new int[10];
}
int main()
{
int *a = 0;
Foo( a );
}
Now the memory will be allocated but the pointer A will not be update because the value of pointer A is simply copied to another pointer variable which is parameter of Foo. Once the Foo is returned, a will remain 0. To make it refect that, you should write code like follows
void Foo(int ** a)
{
*a = new int[10];
}
int main()
{
int *a = 0;
Foo( &a );
}
Here you're passing the address of a pointer. The which means that, the value which contains in the pointer will be updated from the Foo function.You can debug through and see how it works.
If you're sure that you will not access the pointer anymore, please use the first type. Otherwise use the second one. Make sure that you set the pointer to NULL to avoid further memory corruptions or dangling pointers.
The thing that confuses me about your question is that most people would not declare a matrix as an int **. The reason for this is that you would be forced to then allocate it in a loop. Your allocation function would require two parameters, which are the dimensions of the array like this:
void AllocMat(int *** mat, int n, int m) {
int ** result = new int * [ n ];
for (int x=0; x<n; x++) {
result[x] = new int [ m ];
}
*mat = result;
}
If this were the case, the corresponding deallocation function would require knowledge of the size of n as follows:
void DeallocMat(int *** mat, int n) {
if (mat == NULL || *mat == NULL) return;
int ** tmp = *mat;
for (int x=0; x<n; x++) {
if (tmp[x] != NULL) delete [] tmp[x];
}
delete [] tmp;
*mat = NULL;
}
With this approach, you could access your matrix like this:
int ** mat = NULL;
AllocMat(&mat, n, m);
for (int x=0; x<n; x++) {
for (int y=0; y<m; y++) {
mat[x][y] = 1;
}
}
DeallocMat(&mat, n);
Usually, people allocate matrices as a single buffer of memory to avoid extra allocations and pointer indirections, which is how I recommend you do it. In that case, you allocation function would look like this:
void AllocMat2(int ** mat, int n, int m) {
*mat = new int [ n * m ];
}
And the corresponding deallocation function like this:
void DeallocMat2(int ** mat) {
if (mat != NULL && *mat != NULL) {
delete [] *mat;
*mat = NULL;
}
}
And you would access it follows:
int * mat2 = NULL;
AllocMat2(&mat2, n, m);
for (int x=0; x<n; x++) {
for (int y=0; y<m; y++) {
mat2[x * n + y] = 1;
}
}
DeallocMat2(&mat2);
Either way works, but if you pass a pointer to the pointer you need to dereference it first. And the size parameter is redundant.
void DeallocMat(int **mat)
{
delete[] mat;
}
void DeallocMat(int ***mat)
{
delete[] *mat;
*mat = NULL;
}