Pointer Help in C++ - c++

I am new to c++(have a java background) and thus pointers are sort of new to me. I am dealing with an array of pointers where each index points to an object on the heap as so:
Deck::Deck()
{
seed = rand()%100; //this will be used in shuffle method
srand(seed);
for(int i=0;i<deckSize;i+=3) //deckSize=12 in this case, p defined as CardTypes* p[deckSize]
{
p[i]= new Infantry();
p[i+1] = new Artillery();
p[i+2] = new Cavalry();
}
}
All 3 of these classes are subclasses of the class CardTypes(which was only created so I could store diff types in an array).
class CardTypes
{
public:
virtual string getCard() = 0;
virtual ~CardTypes() {};
};
class Infantry: public CardTypes
{
const string name = "Infantry";
public:
string getCard(); //this simply returns "name" so that I can differentiate each object in the array by a data value
};
class Artillery:public CardTypes
{
const string name= "Artillery";
public:
string getCard();
};
class Cavalry:public CardTypes
{
const string name = "Cavalry";
public:
string getCard();
};
Although not a great way to do it, I have created another array of pointers(CardTypes* s[deckSize) which copies pointers from p into s randomly(thus mimicking a shuffle in a deck of cards):
void Deck::shuffle() //this is the method that puts objects in s to be grabbed in draw()
{
int j = 0;
int k = 1;
int l = 2; //initial setup(index 0 will have Infantry, index 1 will have Artillery and index 3 will have Cavalry and this pattern continues throughout p)
int n = rand()%3 + 1; //gives random # between 1 and 3 1=infantry,2 = artillery,3 = cavalry
int i=0; //counter for loop
while(i<deckSize)
{
n = rand()%3+1;
if(n==1)
{
if(j>9) //means no more infantry cards as due to pattern of p
infantry cards stop after index 9
{
continue; //used to reset loop foranother iteration(will get random number,I know this is bad for time complexity)
}
else
{
s[i] = p[j]; //copy "Infantry" pointer to s
j+=3;
i++;
}
}
else if(n==2)
{
if(k>10)//means no Artillery cards due to pattern in p
{
continue;
}
else
{
s[i] = p[k];//copy "Artillery" pointer to s
k+=3;
i++;
}
}
else
{
if(l>11) //means no more cavalary cards due to pattern in p
{
continue;
}
else
{
s[i] = p[l]; //copy "Cavalry" pointer to s
l+=3;
i++;
}
}
}
}
Now my issue is i am trying to create a draw method that grabs a pointer from s and returns it. My program completely crashes when I attempt this and I am not sure why:
CardTypes* Deck::draw() //draws a card from the deck and returns it
{
CardTypes* card = s[deckSize];
delete s[deckSize];//clear heap
s[deckSize] = NULL;//remove what pointer was pointing too (as card has been drawn)
deckSize--;
return card;
}
I then attempt to call this method:`
int main()
{
Deck d1;
d1.shuffle(); //this works
d1.getCurrentDeck();//this works, just prints out each objects getCard() method in s
CardTypes* card = d1.draw();//does not cause a crash
cout<<"Card:"<<card->getCard() <<"\n";//crashes here
}
This issue is probably due to my inexperience with pointers but any help would be appreciated. Also note I delete the arrays after I am done with the program using delete [] p and delete [] s, I have not included this in the code as it is not of issue right now.

You are struggling with pointer ownership. You understand that in C++ one must delete a pointer when it is no longer needed, but in Deck::draw you delete a pointer when it is still needed.
CardTypes* Deck::draw()
{
CardTypes* card = s[deckSize]; // s and card point to same allocation
delete s[deckSize]; // boom! card points to garbage.
s[deckSize] = NULL;
deckSize--;
return card;
}
You can use raw pointers, but you need to do it with a lot of coding maturity and deliberation.
Or you can say Smurf it and protect yourself from accidents like this with smart pointers. What is a smart pointer and when should I use one?
std::unique_ptr bundles ownership of a pointer. Only one std::unique_ptr is allowed at a time. You can't copy it. It as to be moved everywhere, transferring ownership from one holder to the next. But in the end there can be only one. You have to go out of your way to be stupid with a unique_ptr. Making five unique_ptrs and pointing them all at the same pointer, yeah you can do that. Put a self-destructing Automatic variable in a unique_ptr, yeah you can do that (and sometimes you do, but with a custom deleter that does nothing).
unique_ptr is the owner of the pointer. Whoever has the unique_ptr is owner by proxy because as soon as they get rid of the unique_ptr, the pointer goes with it.
Let's take a look at what we can do with a std::unique_ptr<CardTypes> to corral these wild pointers. If s is an array of unique_ptrs, std::unique_ptr<CardTypes> s[MAX_DECK_SIZE];, draw becomes
std::unique_ptr<CardTypes> Deck::draw()
{
std::unique_ptr<CardTypes> card = std::move(s[deckSize]);
// delete s[deckSize]; don't. Card now owns the card
// s[deckSize] = NULL; handled by moving ownership
deckSize--;
return card;
}
This can be simplified to
std::unique_ptr<CardTypes> Deck::draw()
{
return std::move(s[deckSize--]);
}
decksize-- is a post decrement so it happens after and the rest of the work is managed by the unique_ptr when it is moved out of s;
Sadly this means
s[i] = p[j];
ain't so easy anymore. You need
s[i] = std::move(p[j]);
But only if p no longer needs its jth element, because s[i] owns it now, baby.
Too little information has been provided in the question to wrangle this properly, but...
It's very possible that you could keep p full of unique_ptrs and load s with raw pointers whose lifespan is governed by p and pass s's pointers around naked and free without ever deleteing them because you know p has your back. So long as you keep p around longer than s and whoever s gives pointers to. It all comes back to ownership and in this case p owns all the Cards.
That turns
s[i] = std::move(p[j]);
into
s[i] = p[j].get();
and draw into
CardTypes * Deck::draw()
{
return s[deckSize--];
}
and makes life really, really easy.

Your problem is you are deleting the instance and, after that, you want to use it.
You are creating many instances:
for(int i=0;i<deckSize;i+=3) //deckSize=12 in this case, p defined as CardTypes* p[deckSize]
{
p[i]= new Infantry();
p[i+1] = new Artillery();
p[i+2] = new Cavalry();
}
The size of your array is determined by the variable deckSize.
In your function Deck::draw() your have some errors:
You are set a pointer of an instance of CardType with this code: CardTypes* card = s[deckSize]; But the array s has an index base 0, so s[deckSize]is accessing another memory sector that is not assigned to array s (Could a Memory Access Violation). use s[deckSize-1] instead of s[deckSize]..
You are release the memory that was assigned to pointer card and this pointer is returned to be used outside the function, which try to use this instance but is doesn't exist any more. So the memory which card and s[deckSize] share is released. Don't forget that s[deckSize] could raise a Memory Access Violation.
Check your code:
CardTypes* Deck::draw() //draws a card from the deck and returns it
{
CardTypes* card = s[deckSize-1]; //Assign the pointer to card.
delete s[deckSize-1];//DELETE THE INSTANCE (The memory that
return card; //The card points to a memory previously released.
}
Here is the moment that you are trying to use an unallocated:
CardTypes* card = d1.draw();//Get the pointer to s[deckSize-1]
cout<<"Card:"<<card->getCard() <<"\n";//crashes here
UPDATE:
Answer your comment, You can do this:
1.- Get the referencer to instance: CardTypes* card = s[deckSize-1];.
2.- Set the slot of your array in NULL and decrease the index:
s[deckSize-1]=NULL;
deckSize--;.
3.- Return de reference saved in card to upper level: return card;.
4.- Use the reference returned as you need it:
CardTypes* card = d1.draw();
cout<<"Card:"<<card->getCard() <<"\n";.
5.- Finally, delete de instance once you have finished to use it, for example just after the invocation of getCard():
cout<<"Card:"<<card->getCard() <<"\n";
delete card;
It's important to say that you decide where and when reserve, use and release the memory; just keep in mind to do it in an organized way and apply best practices, like these:
https://www.codeproject.com/Articles/13853/Secure-Coding-Best-Practices-for-Memory-Allocation
http://www.embeddedstar.com/technicalpapers/pdf/Memory-Management.pdf

Related

Deleting dynamic elements in a vector

I have a program that has a vector. The vector takes pointers to an object which I dynamically create in my program. I then wish to delete these dynamic objects from the vector. For example:
int main()
{
vector<Account*> allAccounts;
auto timeDone = chrono::system_clock::now();
time_t transactionTime = chrono::system_clock::to_time_t(timeDone);
Account* a1 = new Savings(0, "Savings");
Account* a2 = new Current(0, "Current");
allAccounts.push_back(a1);
allAccounts.push_back(a2);
Transaction* initialTransaction = new Transaction("Initial Deposit", transactionTime, balanceAnswer);
allAccounts[0]->addTransaction(initialTransaction);
allAccounts[1]->addTransaction(initialTransaction);
for (int i = 0; i < allAccounts.size(); i++)
{
delete allAccounts[i]; //deletes all dynamically created accounts
}
}
I believed this was fine to do, however I'm starting to wonder if this does correctly delete the pointers in the vector. However I used a cout << allAccounts.size() after the delete and it still gives the size as 2 as if the account pointers were still in the vector.
Is this meant to happen?
Another note is that the Account object also has a vector of dynamic pointers that get passed from main in a function (allAccounts[i]->addObject(object)) and then these objects get deleted in a destructor in the same way. Is this also a valid thing to do?
Just so I get my worries out the way, this is what I do in account:
float balance;
string accountType
private vector <Transaction*> history;
Account::Account(float b, string a)
{
balance = b;
accountType = a;
}
void Account::addTransaction(Transaction* t)
{
history.push_back(t);
}
Account::~Account()
{
for (int i = 0; i < history.size(); i++)
{
delete history[i];
}
history.clear();
}
What you are doing is fine (assuming Account has a virtual destructor) and there is no memory leak. The size of the vector is not affected by deleting the pointers you store in it.
The destructor needs to be virtual to not cause your program to have undefined behavior.
I would recommend storing a smart pointer like std::unique_ptr<Account> in the vector instead though. That would make the destruction of the stored objects automatic when the vector.is destroyed.

How to delete class as this and set it as null in c++

So, I have an array of a class called "Customer"
Customer** customersarray[] = new Customer*[customer];
I'm receiving int customer with cin.
anyways, in customer.cpp, there is a method called void deactivate().
which goes like this:
void Custmoer::deactivate()
{
if (this != NULL)
remove this;
//this = NULL; I want to do this but it doesn't work.
}
and the purpose of this is to remove it from customer array when satisfies a certain condition. So for example,
for (int i = customer - 1; i >= 0; i--)
{
if (customersarray[i]->getAngerLevel() == 5) {
customersarray[i]->deactivate();
}
for (int z = i; i < customer - 1; i++) {
*(customersarray + z) = *(customersarray + z + 1);
}
customer--;
}
so my first questions are:
why does this = NULL not work?
is there a simpler way to remove something from pointer array when a condition is satisfied? (for example, remove all customers that has anger level of 5.)
Your mistake is thinking that you can remove something from a Customer* array by some magic inside the Customer class, but that's not true. Just remove a customer from the customer array where ever the customer array is. For instance using remove_if
#include <algorithm>
Customer** customersarray = new Customer*[customer];
...
customer = std::remove_if(customersarray, customersarray + customer,
[](Customer* c) { return c->anger() == 5; }) - customersarray;
This updates the customer variable to be the new size of the array, but doesn't free or reallocate any memory. Since you are using dynamic arrays and pointers you are responsible for that.
Which is why you should really not be using pointers or arrays, but using vectors instead.
std::vector<Customer> customerVector;
Life will be so much simpler.
Type of "this" is a constant pointer which means you cant change where it points
Your function can return a boolean and if its true just set your pointer to null
You'll be much better off using a std::vector, all memory memory management gets much safer. You cannot modify the this pointer, but that would be meaningless anyway:
It is a local variable, so any other pointer outside would not be changed, not even the one you called the function on (x->f(): the value of x is copied into this).
It contains the address of the current object - the current object is at a specific memory location and cannot be moved away from (not to be mixed up with 'moving' in the context of move semantics!).
You can, however, delete the current object (but I don't say you should!!!):
class Customer
{
static std::vector<Customer*> customers;
public:
void commitSuicide()
{
auto i = customers.find(this);
if(i != customers.end())
customers.erase(i);
delete this;
}
}
Might look strange, but is legal. But it is dangerous as well. You need to be absolutely sure that you do not use the this pointer or any other poiner to the current object any more afterwards (accessing non-static members, calling non-static functions, etc), it would be undefined behaviour!
x->commitSuicide();
x->someFunction(); // invalid, undefined behaviour!!! (x is not alive any more)
Similar scenario:
class Customer
{
static std::vector<std::unique_ptr<Customer>> customers;
public:
void commitSuicide()
{
auto i = customers.find(this);
if(i != customers.end())
{
customers.erase(i); // even now, this is deleted!!! (smart pointer!)
this->someFunction(); // UNDEFINED BEHAVIOUR!
}
}
}
If handling it correctly, it works, sure. Your scenario might allow a much safer pattern, though:
class Customer
{
static std::vector<std::unique_ptr<Customer>> customers;
public:
Customer()
{
customers->push_back(this);
};
~Customer()
{
auto i = customers.find(this);
if(i != customers.end())
customers.erase(i);
}
}
There are numerous variations possible (some including smart pointers); which one is most appropriate depends on the use case, though...
First of all, attending to RAII idiom, you are trying to delete an object before using its destructor ~Customer(). You should try to improve the design of your Customer class through a smart use of constructor and destructor:
Customer() {// initialize resources}
~Customer() {// 'delete' resources previously created with 'new'}
void deactivate() {// other internal operations to be done before removing a customer}
Then, your constructor Customer() would initialize your internal class members and the destructor ~Customer() would release them if necessary, avoiding memory leaks.
The other question is, why do you not use another type of Standard Container as std::list<Customer>? It supports constant time removal of elements at any position:
std::list<Customer> customers
...
customers.remove_if([](Customer foo) { return foo.getAngerLevel() == 5; });
If you only expect to erase Customer instances once during the lifetime of the program the idea of using a std::vector<Customer> is also correct.

Order of destructors

I have these kind of classes:
Game:
class Game {
private:
BoardField*** m_board_fields;
public:
Game() {
m_board_fields = new BoardField**[8];
for (int i = 0; i < 8; i++) {
m_board_fields[i] = new BoardField*[8];
}
}
Game::~Game() {
for (int i = 0; i < 8; i++) {
for (int j = 0; i < 8; j++) {
delete m_board_fields[i][j];
}
delete[] m_board_fields[i];
}
delete[] m_board_fields;
}
}
BoardField:
class BoardField {
private:
ChessPiece* m_piece;
....
public:
BoardField::~BoardField() {
delete m_piece;
}
}
And on the close of the program I get error in ~BordField:
Exception thrown: read access violation.
this was 0xFDFDFDFD.
Did I made my destructors incorrect? What is the best way to clear memory from multidimensional array ?
There is are two fundamental flaws in your design:
there is no clear ownership of the BoardFields: someone create it, someone else deletes it. It can work if you're very cautious but it's error prone.
you do not ensure the rule of 3 (or better 5): if you have any piece of code where you create a copy of either your Game or a of any BoardField the first object that gets destroyed will delete the m_piece pointer, and when the second object gets destroyed, it'll try to delete a second time the same pointer, which is UB.
There is a third important issue: you're over-using raw pointers:
if m_board_fields is a 2d array of fixed size, make it a fixed size array (aka BoardField* m_board_fields[8][8]). If you want to keep its size dynamic, use vectors.
a cell of m_board_field could be a pointer if there's some polymorphism expected. But this seems not the case here, as obviously ChessPiece is the polymorphic class. So better use plain fields instead of pointers (aka BoardField m_board_fields[8][8]).
Finally, instead of using raw pointer to ChessPiece, better use a shared_ptr<ChessPiece> : you don't have to worry about shallow pointer copies and double delete; the shared_ptr will take care of itself and destroy the object if it's no longer used.

Pointer Copy to Out of Scope c++

Today i went back and investigated an error i got in an old project. It's not exactly an error, rather, i don't know how to do what i need to do. Don't really want to go into the details of the project as it is old and buggy and inefficient and more importantly irrelevant. So i coded a new sample code:
#include <iostream>
#include <vector>
#include <time.h>
#include <random>
#include <string>
class myDoc;
class myElement
{
int myInt;
std::string myString;
myElement * nextElement;
//a pointer to the element that comes immediately after this one
public:
myElement(int x, std::string y) : myInt(x), myString(y){};
friend myDoc;
};//an element type
class myDoc
{
std::vector<myElement> elements;
public:
void load();
~myDoc()
{
//I believe i should delete the dynamic objects here.
}
};// a document class that has bunch of myElement class type objects as members
void myDoc::load()
{
srand(time(0));
myElement * curElement;
for (int i = 0; i < 20; i++)
{
int randInt = rand() % 100;
std::string textInt = std::to_string(randInt);
curElement = new myElement(randInt,textInt);
//create a new element with a random int and its string form
if (i!=0)
{
elements[i-1].nextElement = curElement;
//assign the pointer to the new element to nextElement for the previous element
//!!!!!!!!!!!! this is the part that where i try to create a copy of the pointer
//that goes out of scope, but they get destroyed as soon as the stack goes out of scope
}
elements.push_back(*curElement);// this works completely fine
}
}
int main()
{
myDoc newDoc;
newDoc.load();
// here in newDoc, non of the elements will have a valid pointer as their nextElement
return 0;
}
Basic rundown: we have a document type that consists of a vector of element type we define. And in this example we load 20 random dynamically allocated new elements to the document.
My questions/problems:
When the void myElement::load() function ends, the pointer and/or the copies of it goes out of scope and get deleted. How do i keep a copy that stays(not quite static, is it?) at least until the object it points to is deleted?
The objects in the elements vector, are they the original dynamically allocated objects or are they just a copy?
I allocate memory with new, how/when should i delete them?
Here is a picture i painted to explain 1st problem(not very accurate for the specific example but the problem is the same), and thank you for your time.
Note: I assumed you want a vector of myElement objects where each one points to the element next to it. It is unclear if you want the objects in elements to point to copies of them, anyway it should be pretty easy to modify the code to achieve the latter
This is what happens in your code:
void myDoc::load()
{
..
curElement = new myElement(n,m); // Create a new element on the heap
...
// If this is not the first element we inserted, have the pointer for the
// previous element point to the heap element
elements[i-1].nextElement = curElement;
// Insert a COPY of the heap element (not the one you stored the pointer to)
// into the vector (those are new heap elements copied from curElement)
elements.push_back(*curElement);// this works completely fine
}
so nothing gets deleted when myDoc::load() goes out of scope, but you have memory leaks and errors since the pointers aren't pointing to the elements in the elements vector but in the first heap elements you allocated.
That also answers your second question: they're copies.
In order to free your memory automatically, have no leaks and point to the right elements you might do something like
class myElement
{
int a;
std::string b;
myElement *nextElement = nullptr;
//a pointer to the element that comes immediately after this one
public:
myElement(int x, std::string y) : a(x), b(y){};
friend myDoc;
};//an element type
class myDoc
{
std::vector<std::unique_ptr<myElement>> elements;
public:
void load();
~myDoc()
{}
};// a document class that has bunch of myElement class type objects as members
void myDoc::load()
{
srand((unsigned int)time(0));
for (int i = 0; i < 20; i++)
{
int n = rand() % 100;
std::string m = std::to_string(n);
//create a new element with a random int and its string form
elements.emplace_back(std::make_unique<myElement>(n, m));
if (i != 0)
{
//assign the pointer to the new element to nextElement for the previous element
elements[i - 1]->nextElement = elements[i].get();
}
}
}
Live Example
No need to delete anything in the destructor since the smart pointers will be automatically destroyed (and memory freed) when the myDoc element gets out of scope. I believe this might be what you wanted to do since the elements are owned by the myDoc class anyway.

Memory management when working with pointers in C++

I have these scenarios and I want to know if I manage my memory correctly. I watch the memory consumption in the Task Manager when I start the executable and see how memory is not popped back to the initial amount, which leads me to suspect that I don't clear memory where is needed.
So, in this first case I have a function that adds a new element to a dynamic array:
struct Color {
int R;
int G;
int B;
}
int TotalColors;
Color* Rainbow;
void AddColor(Color NewColor) {
// So, I create a new array of size TotalColors+1
Color* NewRainbow = new Color[TotalColors+1];
// Now I add the existing elements
for (int i=0; i<TotalColors; i++) {
NewRainbow[i] = Rainbow[i];
}
// And lastly, I add the new element
NewRainbow[TotalColors] = NewColor;
// Now, I assign the NewRainbow to Rainbow (I don't know if it's correct)
Rainbow = NewRainbow;
}
So, in this case, do you think I miss something? This is working but I want to make sure the unused stuff is removed from memory.
I also have a function to remove an element, which looks like this:
void RemoveColor(Color Removable) {
// Again, I create a new array of size TotalColors-1
Color* NewRainbow = new Color[TotalColors-1];
// I scan the list and add only those elements which are not 'Removable'
for (int i=0; i<TotalColors; i++) {
// Let's suppose that Removable exists in the list
if (Rainbow[i].R != Removable.R && Raibow[i].G != Removable.G && ... {
NewRainbow [i] = Rainbow[i];
}
}
// Again, the same operation as above
NewRainbow[TotalColors] = NewColor;
Rainbow = NewRainbow;
}
In this case, I don't know what happens with Rainbow[Removable], I mean, the element of the array that is removed.
And the last case, is this, where I try to send the pointer of an element from the array to a function.
Color* GetColor(int Index) {
Color* FoundColor;
// Scan the array
for (int i=0; i<TotalColors; i++) {
if (i == Index) FoundColor = &Rainbow[i];
}
return FoundColor;
}
// And I use it like this
void ChangeColor(int Index) {
Color* Changeable;
Changeable = GetColor(Index);
SetRGB(Changeable, 100, 100, 100);
}
// And this is what changes the value
void SetRGB(Color* OldRGB, int R, int G, int B) {
(*oldRGB).R = R;
(*oldRGB).G = G;
(*oldRGB).B = B;
}
And this is it. So, this works but I am not sure if with so many pointers I didn't forget to delete something. For example, when I RemoveColor I don't see the memory changed (maybe some bytes don't make the difference) and I just want some professional eye to tell me if I missed something. Thanks!
In the first function AddColor() you are not deleting the previously allocated memory.
Rainbow = NewRainbow; // leaking the memory Rainbow was previously pointing to.
Change that last line to:
delete[] Rainbow;
Rainbow = NewRainbow;
Same thing with RemoveColor()
Any time you use the new operator it needs to have a corresponding delete. Also, if you are allocating an array with new[] as in your case, it must have a corresponding delete[].
In order not to worry whether you've forgotten to delete a pointer, you shouldn't use plain pointers. Instead, use smart pointers such as
std::shared_ptr
std::unique_ptr
etc.
or, if you don't have C++11 yet, use
boost::shared_ptr
boost::scoped_ptr
More on smart pointers, see Wikipedia and the specific documentation.