I am encountering the following bug.
I have a class Foo . Instances of this class are stored in a std::vector vec of class B.
in class Foo, I am creating an instance of class A by allocating memory using new and deleting that object in ~Foo().
the code compiles, but I get a crash at the runtime. If I disable delete my_a from desstructor of class Foo. The code runs fine (but there is going to be a memory leak).
Could someone please explain what is going wrong here and suggest a fix?
thank you!
class A{
public:
A(int val);
~A(){};
int val_a;
};
A::A(int val){
val_a = val;
};
class Foo {
public:
Foo();
~Foo();
void createA();
A* my_a;
};
Foo::Foo(){
createA();
};
void Foo::createA(){
my_a = new A(20);
};
Foo::~Foo(){
delete my_a;
};
class B {
public:
vector<Foo> vec;
void createFoo();
B(){};
~B(){};
};
void B::createFoo(){
vec.push_back(Foo());
};
int main(){
B b;
int i =0;
for (i = 0; i < 5; i ++){
std::cout<<"\n creating Foo";
b.createFoo();
std::cout<<"\n Foo created";
}
std::cout<<"\nDone with Foo creation";
std::cout << "\nPress RETURN to continue...";
std::cin.get();
return 0;
}
You need to implement a copy constructor and an assignment operator for Foo. Whenever you find you need a destructor, you alnmost certainly need these two as well. They are used in many places, specifically for putting objects into Standard Library containers.
The copy constructor should look like this:
Foo :: Foo( const Foo & f ) : my_a( new A( * f.my_a ) ) {
}
and the assignment operator:
Foo & Foo :: operator=( const Foo & f ) {
delete my_a;
my_a = new A( * f.my_a );
return * this;
}
Or better still, don't create the A instance in the Foo class dynamically:
class Foo {
public:
Foo();
~Foo();
void createA();
A my_a;
};
Foo::Foo() : my_a( 20 ) {
};
If you don't specify a copy constructor, the compiler makes one for you. Your compiler-generated copy constructor looks like this:
Foo::Foo(const Foo& copy)
: my_a(copy.my_a)
{}
Woops! You're copying just the pointer but not the pointed-to memory. Both your temporary Foo() in createFoo() and the one copied in to the vector point to the same memory, so the memory is deleted twice, which crashes your program on the second delete.
You should create a copy constructor that looks something like this:
Foo::Foo(const Foo& copy)
: my_a(new A(*copy.my_a))
{}
Note this crashes if copy has a NULL my_a member, and it also invokes the copy constructor on A, which you haven't specified either. So you'll want to make some further changes. You'll also want an operator= overload too.
The Foo object is copied and at the destruction of every copy, delete is called on the same pointer value my_a.
Implement the copy and assignment operator for Foo or use a smart pointer.
Foo( const Foo& s) : my_a( s.my_a ? new A(*s.my_a) : 0) {
}
Foo& operator= (const Foo& s) {
Foo temp(s);
temp.swap (*this);
return *this;
}
void swap (Foo &s) {
std::swap (my_a, s.my_a);
};
Related
If the new operator was written in a function argument or constructor argument like:
Foo* f = new Foo(new Baz(0, 0));
// how to delete "new Baz(0, 0)"?
delete f;
I know it can be written to:
Baz* b = new Baz(0, 0)
Foo* f = new Foo(b);
delete b;
delete f;
But it became complicated, is there any better way?
Should I do something like this:
Class Foo {
private:
Baz* _b;
public:
Foo(Baz* b) : _b(b) {}
~Foo() {
delete _b;
}
}
// so that when I delete foo will also delete baz;
Following my own recommendation about the rule of zero and using std::unique_ptr, I would do something like this:
class Foo
{
public:
Foo(int a, int b)
baz_{ std::make_unique<Baz>(a, b) }
{
}
private:
std::unique_ptr<Baz> baz_;
};
And
auto foo = std::make_unique<Foo>(0, 0);
With this the foo object own its own unique Baz object.
If you want Foo to by copyable then use std::shared_ptr and std::make_shared instead.
More or less Yes, you should delete an allocated field in the destructor.
If the class has children, make the destructor virtual.
However you could have passed an existing pointer. And then the field is not owned.
You can use one of the ptr classes, i.e. std::unique_ptr for the Baz.
Or defer the deletion to the caller in some form:
Baz* _b; // Or Baz _b.
Foo(const Baz& b) : _b(new Baz(b)) {} // When feasible a copy.
From design point it would
I, unfortunately, can't describe my problem properly, but:
When I am trying to change a pointer value bar defined in base class 'A' from a child class 'B' with method foo() it gives me a segfault, because the pointer bar is null:
#include <iostream>
class A {
protected:
virtual void foo() {};
int* bar;
public:
void eval(){
foo();
std::cout << *bar;
}
};
class B : public A {
void foo() override {
*bar = 10; //segfault
}
};
int main(){
B* foobar = new B();
foobar->eval();
}
But, if the bar is not a pointer, but a normal variable it works fine.
Your bar is not pointing to anything, so as it does not point at an int you cannot assign a value to its int (*bar = 10 = segfault). Add a constructor to A that fixes that:
class A {
protected:
A() { // <- Constructor
bar = new int(0);
}
A(const A& other) // <- Copy sonstructor
{
bar = new int(*other.bar);
}
A& operator=(A other) // Assignment operator
{
std::swap(bar, other.bar);
return *this;
}
virtual ~A() { // <- Destructor
delete bar;
}
virtual void foo() {}
int* bar = nullptr;
public:
void eval() {
foo();
std::cout << *bar;
}
};
Then the rest of your code works, and eval() prints 10 as intended. Note, adding a destructor to clean up bar later is needed to prevent memory leaks.
Edit:
As very correctly pointed out by MikeCAT, I was much too hasty and violated the Rule of three in my answer. If you do dynamic allocation you will want both a destructor, a copy constructor, and an assignment operator. I have added those to the code above.
I'm designing a class that's wrapper of a 2D array. Anything seems ok, except the destruction function. I don't know why it throws an access violent reading.
I have tried to detect what happened and I still can't solve this problem. I need your help. Thank you.
class ClassA
{
int Num;
public:
ClassA()
{}
~ClassA(void)
{}
};
class ClassB
{
ClassA* pA;
public:
ClassB()
{}
ClassB(ClassA obj)
{
pA = new ClassA[1];
pA[0] = obj;
}
~ClassB(void)
{
delete[] pA;
}
ClassB::ClassB(ClassB& src)
{
this->~ClassB();
pA = new ClassA[1];
pA[0] = src.pA[0];
}
ClassB& ClassB::operator =(const ClassB& src)
{
if (this == &src)
return *this;
this->~ClassB();
pA = new ClassA[1];
pA[0] = src.pA[0];
return (*this);
}
};
ClassB Test5()
{
ClassA A;
ClassB B( A );
return B;
}
void Test6()
{
ClassB B;
B = Test5();
}
The exception will be thrown after finishing of Test6 function.
Get out of the habit of explicitly calling destructors. Such an act does not reinitialise the object or its (non-static) members - it logically destroys the object so it cannot be used.
this->~ClassB() makes any attempt to access non-static members of the current object (i.e. *this) give undefined behaviour.
For example, in the copy constructor of ClassB
ClassB::ClassB(ClassB& src)
{
this->~ClassB();
pA = new ClassA[1];
pA[0] = src.pA[0];
}
the accesses of pA in the last two statements are (implicitly) this->pA. So they both have undefined behaviour.
There are circumstances where explicitly calling a destructor is appropriate. But assignment operators and copy constructors are generally not among those circumstances.
Consider the following code:
#include <iostream>
#define P_(x) std::cout << x << std::endl
class B {
public:
B() { P_("B::B()"); }
B(const B&) { P_("B::B(const B&)"); }
B(B&&) { P_("B::B(B&&)"); }
~B() { P_("B::~B()"); }
B& operator=(const B&) { P_("B::op=(const B&)"); return *this; }
B& operator=(B&& b) { P_("B::op=(B&&)"); return *this; }
};
class Foo {
public:
void setB(const B& b) { mB = b; }
private:
B mB;
};
B genB() {
return B();
}
int main() {
Foo f;
f.setB(genB());
}
Suppose B is a type that is difficult to copy-construct. I'd like to generate some B (with the function genB) and store it in a Foo. Since genB returns a temporary result, I'd expect that a move constructor would be used.
However, when I run the code, I get this output:
B::B()
B::B()
B::op=(const B&)
B::~B()
B::~B()
This clearly shows that two B's get created and destroyed, but that the second is a copy, and not a move of the first.
What is the best way to get move constructors used whenever possible?
Do I need to call std::move() somewhere?
Do I need a separate overload for a B& and a B&&?
Is there something else entirely that I'm missing?
You could overload that setB function:
class Foo {
public:
void setB(const B& b) { mB = b; }
void setB(B&& b) { mB = std::move(b); }
private:
B mB;
};
Or, you can use the "pass by value" way:
class Foo {
public:
void setB(B b) { mB = std::move(b); }
private:
B mB;
};
Here, the parameter b will be move constructed when possible or copy constructed otherwise.
The first B instance is the one created when creating your Foo instance :
Foo f;
This is because your Foo class has a B member called mB.
The second B instance is the one created by the genB() call.
The assignment operator is called because of the assignment you perform in the Foo::setB function :
mB = b;
Nowhere is there a chance to use a copy or move constructor.
I have wrote a program that use inheritance, everything is OK but an error that I think shouldn't not be here naturally.
here is my program:
class A
{
protected:
int x;
public:
A(){};
~A(){};
A* operator=(const A* other)
{
this->x = other->x;
return this;
}
};
class B : public A
{
public:
B() : A(){};
~B(){};
};
class C
{
protected:
A *a;
public:
C(const A* other){ *(this->a) = other; };
};
int main()
{
B *b = new B();
C *c = new C(b);
return 0;
}
It produces an execution time error in the statement 'this->x = other->x;'.
What about this?
*(this->a) is undefined behavior, because this->a wasn't initialized - it's just a dangling pointer.
You can use a = new A; *a = other (the this-> in this case is redundant), but this isn't the proper C++ way - you should use RAII (look it up) - you wouldn't need destructors, assignment operators or copy constructors if you did.
Also, operator = typically returns *this by reference.
I like Luchian's answer but there is still some places to enhanced in your code, you may still encounter some undefined behavior in your code before you fix other potential bugs.
class A
{
protected:
int x;
public:
A():x(0){} // should always initialize x in constructor
virtual ~A()=0 {} // as A is a base case, ~A must be virtual
A& operator=(const A& other) // a reference will be more practical better?
{
this->x = other.x;
return *this;
}
};
If you don't want to make B object as well which means B is serviced as a base class, you should make its destructor virtual as well, even make it pure virtual.
class B : public A
{
public:
B() : A(){}
virtual ~B(){} =0
{ }
};
*(this->a) = other; is answered by Luchian already. In your code, if you want to keep a copy of pointer which points to A, you can simply initialize a_ptr in member initialize list
see below demo code:
class C
{
protected:
A *a_ptr;
public:
C(A* other):a_ptr(other){ }
};
Finally come to your main function, if b,c are only used in main function, when program finishes, system will claim dynamic allocated memory back, but if you use a,b in a loop, you need to delete them manually.