Crash Issue - C++ Code Design using pointers and destructors - c++

I have a question regarding the following code, which crashes. I am creating a local variable in testfunction() and then pushing it (variable "y") into a list. This variable has a member pointer "b" of object type Ball. As I understand, this local variable "y" is on the stack, so its' destructor will be called after testfunction() is completed. Also, as I understand, a vector "copies" an object into its' list. From what I've learned, it is best practice to delete a pointer in the destructor if one exists in its' class. So, there is "delete b" in the destructor of Example.
The issue that I am having is that the object y.b is being destroyed at the completion of testfunction(). In main(), I am able to see the value of "name" and the address of "b", but the object "b" has already been deleted. I would like to avoid this.
I think there is an issue with the design of the code/use of pointers vs references, etc. Please guide me in the right direction, I am an idiot!
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class Ball
{
public:
int a;
Ball()
{
a = 0;
}
~Ball()
{
cout << "destroyed Ball()" << endl;
}
};
class Example
{
public:
string name;
Ball* b;
Example()
{
name = "";
b = NULL;
}
~Example()
{
cout << "destroying Example()" << endl;
delete b;
}
};
void testfunction(vector<Example>& list)
{
cout << "entered testfunction1()" << endl;
Example y;
y.name = "myName";
y.b = new Ball();
y.b->a = 5;
cout << "y.b->a = " << y.b->a << endl;
list.push_back(y);
cout << "exit testfunction1()" << endl;
}
void testfunction2()
{
cout << "entered testfunction2()" << endl;
Example* y = new Example();
cout << "exit testfunction2()" << endl;
}
int main() {
vector<Example> list;
testfunction(list);
//testfunction2();
if(list[0].b == NULL)
cout << "b is null" << endl;
else
cout << "b is not null" << endl;
cout << list[0].name << endl;
cout << list[0].b << endl;
cout << "list[0].b->a = " << list[0].b->a << endl;
return 0;
}

Since class Example has a pointer member and it tries to own a dynamically allocated resource, it needs non-default copy operations, in other words, it needs user-defined copy constructor and assignment operator.
Inside testfunction, when you copy y into vector, both local y and y copied to the vector point to very same Ball object. The local y is destroyed at the end of the function and Ball is deleted. However, that deleted Ball still pointed by the y in vector
void testfunction(vector<Example>& list)
{
// ...
Example y;
y.name = "myName";
y.b = new Ball();
y.b->a = 5;
list.push_back(y);
// ...
} // <-- destructor for Example y is called and y.b is deleted

Define a copy constructor and an assignement operator for your class Example.
These shall copy properly your object (creating a duplicated Ball object) when pushed back on the vector.
Example(const Example& a)
{
name = a.name; // attention no dynamic allocation
cout << "copy" <<endl;
if (a.b) {
b = new Ball(*a.b); // create a new duplicated Ball
}
else b = NULL;
}
The problem in your example is that the default copy constructor is called when you pushback the object. It copies memberwise and so the pointer to Ball is copied, not the object pointed to.
Yet another alternative could be to replace your Ball* with shared_ptr<Ball> (and accordingly, new Ball with make_shared<Ball>() and the delete b of the object with a b.reset()). The principle is that this smart pointer keeps track of the number of time the object pointed to is used, so that it will not delete it twice, but only when its no longer used anywhere.

Related

New pointer in class method must be casted into a reference

I have two classes, let's call them A and B
class A:
{
public:
//Some functions
A *getNewA() const;
private:
//some attributes
}
class B:
{
public:
//Some functions
private:
A &reftoA;
}
In the main code, I must generate a new A thanks to the A::getNewA() method. And this must go to B::reftoA, as written in class B.
Here is the A::getNewA() method :
A *A::getNewA()
{
A *newA = new A;
return newA;
}
OK. So now I call getNewA and want to store the results in reftoA, which is a reference to A. In a B function (which take a reference to A as parameter)
B::foo(A &paramA)
{
reftoA = *(paramA.getNewA());
}
I thought this should have been working, but it won't.
Because when dereferencing, reftoA will always take the this object and not the new allocated object.
Let's be clearer and let's modify the functions to output the results
A * A::getNewA()
{
A *newA = new A;
std::cout << "New pointer " << newA << std::endl;
std::cout << "this pointer" << this << std::endl;
return A;
}
void B::foo(A &paramA)
{
reftoA = *(paramA.getNewA());
std::cout << "new generated pointer " << &reftoA << std::endl;
}
Here is one of the output :
New pointer : 004FFAEC
this pointer: 0069D888
New generated pointer : 0069D888 //Expected : 004FFAEC
I can't get this "new generated pointer" to be the same than the new pointer the A::getNewA() returns after having allocated the memory. Of course, I guess there is some point with dereferencing the pointer to store it in a reference.
I know reference are used with existing object. Maybe the new object A::getNewA() should allocate memory for won't work as I expected.
I could use pointer instead reference in B::foo(), I know, but I can't
I think I am misunderstanding something about refrence and pointer, but I don't know what.
Any help greatly appreciated
The problem is that you can not reassign a reference. You can change only the value of the referenced object.
So you have to initialize the reference in the initializer list of the constructor of the class B.
Take into account that there is a typo in your code snippet
A*A::getNewA()
{
A *newA = new A;
std::cout << "New pointer " << newA << std::endl;
std::cout << "this pointer" << this << std::endl;
return A;
^^^^^^^^^
}
I think you mean
A*A::getNewA() const
^^^^^
{
A *newA = new A;
std::cout << "New pointer " << newA << std::endl;
std::cout << "this pointer" << this << std::endl;
return newA;
^^^^^^^^^^^
}
Always try to provide a verifiable complete example.
Here is a demonstrative program
#include <iostream>
class A
{
public :
//Some functions
A* getNewA() const
{
A *newA = new A;
std::cout << "New pointer " << newA << std::endl;
std::cout << "this pointer" << this << std::endl;
return newA;
}
private :
//some attributes
};
class B
{
public :
B( const A& a ) : reftoA( *a.getNewA() )
{
std::cout << "&reftoA " << &reftoA << std::endl;
}
private :
A& reftoA;
};
int main()
{
A a;
B b( a );
return 0;
}
Its output is
New pointer 0x2b392afbec20
this pointer0x7ffd287ad0af
&reftoA 0x2b392afbec20
As you can see the values of the New pointer and &reftoA are equal each other.
To make it more clear consider a very simple example
#include <iostream>
int main()
{
int x = 10;
int y = 20;
int &r = x;
r = y;
std::cout << "x = " << x << std::endl;
std::cout << "y = " << y << std::endl;
std::cout << "r = " << r << std::endl;
std::cout << std::endl;
std::cout << "&x = " << &x << std::endl;
std::cout << "&y = " << &y << std::endl;
std::cout << "&r = " << &r << std::endl;
return 0;
}
The program output is
x = 20
y = 20
r = 20
&x = 0x7ffd88ad47a8
&y = 0x7ffd88ad47ac
&r = 0x7ffd88ad47a8
This statement
r = y;
did not force the reference to refer the object y. It just reassigned the value of the referenced object x.
References have to be initialized when they are created.
Yes, you are misunderstanding something.
getNewA() is returning a pointer. it's not a smart pointer, you want to look into those and that's all I'll say on the matter.
on returning a pointer, you must keep a reference to this pointer else you will be unable to delete it and you'll get a memory leak. Thus you MUST have somewhere A* a = A::getNewA() and then later, when you no longer need it delete a;
Where you need to pass a reference to A, you can do foo(*a) which will dereference the pointer and pass a reference to the object it's pointing to.
But in summary, for all new code, smart pointers; there's no excuse to not use them.
Side note: Your code example had a few other issues; such as getNewA wasn't static; I'm going to take the code as a working example of your understanding, and not a working example.
Edit: On re-reading your example, the getNewA is intentionally non-static. I think this question is actually an XY problem (ie you're asking a question you've forced yourself into but isn't your actual problem); but I hope this addresses your misunderstanding of pointers and references.
You are not returning the pointer in the getNewA-Method
A* A::getNewA()
{
A *newA = new A;
return A; // you are returning A and not newA
}
And if you want to reassign the reference to a you can use a std::reference_wrapper
class B :
{
public :
void foo(A& paramA) {
reftoA = *(paramA.getNewA());
}
private :
std::reference_wrapper<A> reftoA;
}

Explaining constructor and copy constructor example

I have this code and I can understand what happening with the contractor of class Fat.
#include <iostream>
using namespace std;
class Block{
int data;
public:
Block(int i = 10) : data(i){
cout << "I just created a Block " << endl;
}
~Block() {
cout << "I will destroy a Block with " << data << endl;
}
void inc() {
data++;
}
};
class A{
Block& block1;
Block block2;
public:
A(Block& blk) : block1(blk), block2(blk) {
cout << "I just created an A " << endl;
}
A(const A& a): block1(a.block1), block2(a.block2) {
cout << "I just created an A by copying but I will also do bad things" << endl;
block1.inc(); block2.inc();
}
~A() {
cout << "I will destroy an A " << endl;
}
void inc() {
block1.inc(); block2.inc();
}
};
class Fat{
A a;
A& ra;
A* pa;
public:
Fat(A& da) : a(da),ra(da) {
pa = new A(da);
cout << "Fat just created !" << endl;
}
~Fat() {
delete pa;
cout << "Fat to be destroyed !" << endl;
}
void inc() {
a.inc();
ra.inc();
pa->inc();
}
};
int main(){
Block block;
A a(block);
Fat fat(a);
fat.inc();
return 0;
}
and the result of this :
I just created a Block
I just created an A
I just created an A by copying but I will also do bad things
I just created an A by copying but I will also do bad things
Fat just created !
I will destroy an A
I will destroy a Block with 12
Fat to be destroyed !
I will destroy an A
I will destroy a Block with 12
I will destroy an A
I will destroy a Block with 11
I will destroy a Block with 15
Why does the copy constructor run twice?
The first "I just created an A by copying but I will also do bad things"comes from this line:
Fat(A& da) : a(da), ra(da) {
a(da) this one calls A's copy constructor
the seconds one from the constructer of class fat:
Fat(A& da) : a(da), ra(da) {
pa = new A(da); //HERE!!
cout << "Fat just created !" << endl;
}
again, with pa = new A(da); you call A's copy constructor.
edit: thank you for formatting your code
The first copy is made to initialise the a member variable in Fat:
Fat(A& da) : a(da), ra(da) {
Then the line
pa = new A(da);
creates a new instance of A on the free store by copying da hence it calls the copy constructor. If instead you wanted to make a pointer to an existing instance of A you should write
pa = &da;

Why does objects get deleted after being inserted into set?

I have set up this example:
class UsefulClass {
public:
int id;
const bool operator< (const UsefulClass &other) const {
return this->id > other.id;
}
UsefulClass(int _id): id(_id) {
std::cout << "constructing " << id << std::endl;
}
~UsefulClass() {
std::cout << "destructing " << id << std::endl;
}
};
std::set<UsefulClass> set;
void create() {
UsefulClass object_1(1);
UsefulClass object_2(2);
set.insert(object_1);
set.insert(std::move(object_2));
std::cout << "create end" << std::endl;
}
int main() {
create();
std::cout << "main end" << std::endl;
}
I am expecting that the objects get destructed once when set gets deleted at the end of the program. But the objects get deleted twice:
constructing 1
constructing 2
create end
destructing 2
destructing 1
main end
destructing 1
destructing 2
Why is set.insert creating a copy here?
The objects in the set are different from the objects local to create(). The ones in the set are constructed using a copy constructor and move constructor, not the constructor UsefulClass(int), so you don't see their construction. The local objects get destroyed when the function create() returns, and then the objects in the set get destroyed at global cleanup after main ends.
object_1 and object_2 are created on stack and will be destroyed once the create() function ends. They need to be copied in the memory managed by set's allocator.
If you redefine the copy constructor, to trace its execution, you'll notice it is called at both inserts.
Rule of 3 applies to your case, if you print from dtor and want meaningful trace you should instrument copy (and maybe move) ctor also.
If you do that output will make sense and things should be properly paired.
Because your objects get copied on insertion into the set. Hence, when the create() function returns, the two local objects are destroyed. After main ends, the two copies that are in the set are destroyed, leading to the second pair of messages.
To illustrate whatever everybody has said before me, just create this simple example (it uses a new copy constructor for the set to use and uses a global variable to generate different ids each time a constructor is executed ---it's been tested, so you can put it in a file and compile):
#include <iostream>
#include <string>
#include <set>
using namespace std;
class UsefulClass {
static int instance;
public:
int id;
int i;
const bool operator<(const UsefulClass &other) const {
return id < other.id;
}
UsefulClass(int i){
id = instance++;
this->i = i;
cout << "constructing "
<< id
<< ":"
<< this->i
<< endl;
}
UsefulClass(const UsefulClass& other) {
id = instance++;
i = other.i;
cout << "constructing "
<< id
<< ":"
<< i
<< endl;
}
~UsefulClass(){
cout << "destructing "
<< id
<< ":"
<< i
<< endl;
}
};
int UsefulClass::instance = 0;
std::set<UsefulClass> myset;
void create() {
UsefulClass object_1(1);
UsefulClass object_2(2);
myset.insert(object_1);
/* please, explain what you mean with std::move, or which move
* have you used for the next statement. All i have is
* std::move(... ) for strings, but you have not defined
* string UsefulClass::operator string();
*/
myset.insert(/*std::move*/(object_2));
cout << "create end"
<< endl;
}
int main() {
create();
cout << "main end"
<< std::endl;
}
so you'll get a different instance id whenever you create a UsefulClass object and you'll see that when inserting into the set they are being copied as new instances. You'll see when each object is being created and when they are being deleted.
$ pru
constructing 0:1
constructing 1:2
constructing 2:1
constructing 3:2
create end
destructing 1:2
destructing 0:1
main end
destructing 2:1
destructing 3:2

How can I create objects while adding them into a vector?

I have a C++ vector. I want the vector to hold a variable number of objects.
Visual Studio 2012 is giving me an error:
Error: type name is not allowed
From this C++ code:
#include <iostream>
#include <vector>
using namespace std;
class testObject{
private:
int someInt;
public:
testObject(int a){ someInt=a; }
void show() { cout<<someInt<<endl; }
};
int main()
{
vector<testObject> testVector;
cout << "Initial size: " << testVector.size() <<endl;
for ( int i = 0; i < 3; i++ )
testVector.push_back(testObject(3));
cout << "New size: " << testVector.size() << endl;
for ( int j = 0; j < 3; j++ )
testVector[ j ].show();
system("pause");
}
But here's another sample of code that looks the same but it's not working.
void Dealer::setNumberOfPlayers( const int tNumber )
{
for ( int i = 0; i < tNumber; i++ )
vectorOfGamers.push_back(Player); // Player is a class that I created
}
Can I create vector to hold objects of Dealer, Bot and Player at the same time? How do I do that? As I know, all objects in vector should be of one type.
To answer the first part of your question, you must create an object of type Player before you can use it. When you say push_back(Player), it means "add the Player class to the vector", not "add an object of type Player to the vector" (which is what you meant).
You can create the object on the stack like this:
Player player;
vectorOfGamers.push_back(player); // <-- name of variable, not type
Or you can even create a temporary object inline and push that (it gets copied when it's put in the vector):
vectorOfGamers.push_back(Player()); // <-- parentheses create a "temporary"
To answer the second part, you can create a vector of the base type, which will allow you to push back objects of any subtype; however, this won't work as expected:
vector<Gamer> gamers;
gamers.push_back(Dealer()); // Doesn't work properly!
since when the dealer object is put into the vector, it gets copied as a Gamer object -- this means only the Gamer part is copied effectively "slicing" the object. You can use pointers, however, since then only the pointer would get copied, and the object is never sliced:
vector<Gamer*> gamers;
gamers.push_back(new Dealer()); // <-- Allocate on heap with `new`, since we
// want the object to persist while it's
// pointed to
Question 1:
vectorOfGamers.push_back(Player)
This is problematic because you cannot directly push a class name into a vector.
You can either push an object of class into the vector or push reference or pointer to class type into the vector. For example:
vectorOfGamers.push_back(Player(name, id))
//^^assuming name and id are parameters to the vector, call Player constructor
//^^In other words, push `instance` of Player class into vector
Question 2:
These 3 classes derives from Gamer. Can I create vector to hold objects of Dealer, Bot and Player at the same time? How do I do that?
Yes you can. You can create a vector of pointers that points to the base class Gamer.
A good choice is to use a vector of smart_pointer, therefore, you do not need to manage pointer memory by yourself. Since the other three classes are derived from Gamer, based on polymorphism, you can assign derived class objects to base class pointers. You may find more information from this post: std::vector of objects / pointers / smart pointers to pass objects (buss error: 10)?
You cannot insert a class into a vector, you can insert an object (provided that it is of the proper type or convertible) of a class though.
If the type Player has a default constructor, you can create a temporary object by doing Player(), and that should work for your case:
vectorOfGamers.push_back(Player());
I know the thread is already all, but as I was checking through I've come up with a solution (code listed below). Hope it can help.
#include <iostream>
#include <vector>
class Box
{
public:
static int BoxesTotal;
static int BoxesEver;
int Id;
Box()
{
++BoxesTotal;
++BoxesEver;
Id = BoxesEver;
std::cout << "Box (" << Id << "/" << BoxesTotal << "/" << BoxesEver << ") initialized." << std::endl;
}
~Box()
{
std::cout << "Box (" << Id << "/" << BoxesTotal << "/" << BoxesEver << ") ended." << std::endl;
--BoxesTotal;
}
};
int Box::BoxesTotal = 0;
int Box::BoxesEver = 0;
int main(int argc, char* argv[])
{
std::cout << "Objects (Boxes) example." << std::endl;
std::cout << "------------------------" << std::endl;
std::vector <Box*> BoxesTab;
Box* Indicator;
for (int i = 1; i<4; ++i)
{
std::cout << "i = " << i << ":" << std::endl;
Box* Indicator = new(Box);
BoxesTab.push_back(Indicator);
std::cout << "Adres Blowera: " << BoxesTab[i-1] << std::endl;
}
std::cout << "Summary" << std::endl;
std::cout << "-------" << std::endl;
for (int i=0; i<3; ++i)
{
std::cout << "Adres Blowera: " << BoxesTab[i] << std::endl;
}
std::cout << "Deleting" << std::endl;
std::cout << "--------" << std::endl;
for (int i=0; i<3; ++i)
{
std::cout << "Deleting Box: " << i+1 << " (" << BoxesTab[i] << ") " << std::endl;
Indicator = (BoxesTab[i]);
delete(Indicator);
}
return 0;
}
And the result it produces is:
Objects (Boxes) example.
------------------------
i = 1:
Box (1/1/1) initialized.
Adres Blowera: 0xdf8ca0
i = 2:
Box (2/2/2) initialized.
Adres Blowera: 0xdf8ce0
i = 3:
Box (3/3/3) initialized.
Adres Blowera: 0xdf8cc0
Summary
-------
Adres Blowera: 0xdf8ca0
Adres Blowera: 0xdf8ce0
Adres Blowera: 0xdf8cc0
Deleting
--------
Deleting Box: 1 (0xdf8ca0)
Box (1/3/3) ended.
Deleting Box: 2 (0xdf8ce0)
Box (2/2/3) ended.
Deleting Box: 3 (0xdf8cc0)
Box (3/1/3) ended.
// create a vector of unknown players.
std::vector<player> players;
// resize said vector to only contain 6 players.
players.resize(6);
Values are always initialized, so a vector of 6 players is a vector of 6 valid player objects.
As for the second part, you need to use pointers.
Instantiating c++ interface as a child class

How is this code running?

Here is the code first, it comes from 'Ruminations on C++' chapter 10
// TestCode.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include <string>
#include <conio.h>
using namespace std;
class P_Node
{
friend class Picture;
protected:
P_Node() : use(1)
{
}
virtual ~P_Node()
{
}
private:
int use;
};
class Picture
{
friend Picture frame(const Picture&);
public:
Picture() : p(new P_Node)
{
cout << "Constructor\t" << "Picture::Picture()" << "\tcalled" << endl;
cout << "Picture p count\t" << p->use << endl;
}
Picture(const Picture& orig) : p(orig.p)
{
cout << "Copy Constructor\t" << "Picture::Picture(const Picture&)" << "\tcalled" << endl;
cout << "Picture p count\t" << p->use << endl;
orig.p->use++;
}
~Picture()
{
cout << "Destructor\t" << "Picture::~Picture()" << "\tcalled" << endl;
cout << "Picture p count before decrease\t" << p->use << endl;
if(--p->use == 0)
{
cout << "Picture p count after decrease\t" << p->use << endl;
cout << "Deleted" << endl;
delete p;
}
}
Picture& operator=(const Picture& orig)
{
cout << "operator=\t" << "Picture& Picture::operator=(const Picture& orig)" << "\tcalled" << endl;
cout << "Picture p count before decrease\t" << p->use << endl;
orig.p->use++;
if(--p->use == 0)
{
cout << "Picture p count after decrease\t" << p->use << endl;
delete p;
}
p = orig.p;
return *this;
}
private:
Picture(P_Node* p_node) : p(p_node)
{
// Why not p_node->use++?
cout << "Picture::Picture(P_Node* p_node)\tcalled" << endl;
}
P_Node *p;
};
class Frame_Pic : public P_Node
{
friend Picture frame(const Picture&);
private:
Frame_Pic(const Picture& pic) : p(pic)
{
cout << "Frame_Pic::Frame_Pic(const Picture& orig)" << "\tcalled" << endl;
}
Picture p;
};
Picture frame(const Picture& pic)
{
return new Frame_Pic(pic);
}
int main(int argc, char* argv[])
{
Picture my_pic;
frame(my_pic);
return 0;
}
The result is:
Constructor Picture::Picture() called
Picture p count 1
Copy Constructor Picture::Picture(const Picture&) called
Picture p count 1
Frame_Pic::Frame_Pic(const Picture& orig) called
Picture::Picture(P_Node* p_node) called
Destructor Picture::~Picture() called
Picture p count before decrease 1
Picture p count after decrease 0
Deleted
Destructor Picture::~Picture() called
Picture p count before decrease 2
Destructor Picture::~Picture() called
Picture p count before decrease 1
Picture p count after decrease 0
Deleted
I have two questions about this code:
Why is the copy constructor called before Frame_Pic's Constructor? In my mind, the copy constructor is called because frame(my_pic) is returning a Picture by value. But that should be called after Frame_Pic's Constructor.
In Picture::Picture(P_Node* p_node), why not increase the use count? isn't this creating a new Picture?
Thanks for any help.
I'm using VC6 under Windows XP.
1, Why is the Copy Constructor called before Frame_Pic's Constructor?
Because the p member is being copy-constructed in the initialization list of Frame_pic's constructor. The initialization list runs before the constructor's body is entered.
In my mind, the Copy Constructor is called because frame(my_pic) is returning a Picture by value. But that should be called after Frame_Pic's Constructor.
frame() is declared to return a Picture instance by value, but it is coded to return a Frame_pic* instead. Frame_pic derives from P_node, and Picture has a constructor that accepts a P_node*, and that constructor is accessible to frame() so the compiler allows it.
2, In Picture::Picture(P_Node* p_node), why not increase the use count? isn't this creating a new Picture?
The use count is on P_node, not Picture. The Picture that frame() returns owns the Frame_pic that frame() creates, whose use count member is already 1 by the Frame_pic constructor. That is why that Picture constructor does not increment the use count - it is already at the correct value.
The Frame_pic contains its own Picture that is copy-constructed from another Picture, so that Picture constructor needs to increment the use count of the original Picture.
The copy constructor is invoked by Frame_Pic's constructor (it's invoked by the initializer : p(pic)). However Frame_Pic's constructor doesn't print until after all initializers have been run.
Because the intended use of the constructor is not documented, it's hard to say. It may be a bug, or it may be 'attach semantics' - that is, it may be considering the case where you take manual control of the P_Node*, then later give it back. However attach semantics is unlikely, as there's no corresponding detach mechanism to return the pointer and clear it without decrementing the refcount. So, most likely a bug.
Note that while this sort of manual reference counting can be good as a learning exercise, modern C++ code generally uses smart pointers (eg, std::shared_ptr or boost::shared_ptr, invasive_ptr, etc) to automate the process.
Frame_Pic(const Picture& pic) : p(pic)
{
cout << "Frame_Pic::Frame_Pic(const Picture& orig)" << "\tcalled" << endl;
}
You initializing 'p' using its copy constructor 'p(pic)', hence it gets called in the order you see