Segfault if change the pointer value from a derived class - c++

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.

Related

Method nonvisibility in base class despite definition in derived class; polymorphism and using `virtual` keyword

#include <iostream>
class A {
protected:
int foo;
};
class B : public A {
public:
B(int bar) { foo = bar; }
int method() { return foo; }
};
class C {
private:
A baz;
public:
C(A faz) { baz = faz; }
A get() { return baz; }
};
int main(void) {
C boo(B(1));
std::cout << boo.get().method() << std::endl;
return 0;
}
I have a base class A which B is a derived class of. Class C takes an A yet I have passed a derived class (B) in its place. No warnings or errors passing a B to C, but I'd like to have method visibility of method() in the above situation.
I'm not very familiar with virtual but I did try to add virtual int method() = 0; to A which lead to further errors.
Consider were I to add a second derived class:
class D : public A {
public:
D(int bar) { foo = bar; }
int method() { return foo+1; }
};
I'd like C to be able to take either B or D and my best assumption would be to take an A and let it handle it.
How do I use polymorphism correctly in this fashion?
Expected output with the below:
int main(void) {
C boo(B(1));
C boz(D(2));
std::cout << boo.get().method() << std::endl;
std::cout << boz.get().method() << std::endl;
return 0;
}
Would be:
1
3
First of all, in order to use A polymorphically, you need to add a virtual destructor, otherwise you will run into undefined behavior when trying to destroy the object. Then the method that you want to call through A must be virtual as well. If it shouldn't have an implementation in the base class itself, make it pure virtual:
class A {
protected:
int foo;
public:
virtual ~A() {}
virtual int method() = 0;
};
Then in C you need to use pointers or references to A, since polymorphism only works with those.
If you want C to own the A, as your code example to suggest, then you need to provide a destructor deleting the pointer and you need to disable copying of the class (or decide on some useful semantics for it):
class C {
private:
C(const C&); // Don't allow copying
C& operator=(const C&); // Don't allow copying
A* baz;
public:
C(A* faz) : baz(faz) { }
~C() { delete baz; }
A& get() { return *baz; }
};
int main(void) {
C boo(new B(1));
C boz(new D(2));
std::cout << boo.get().method() << std::endl;
std::cout << boz.get().method() << std::endl;
return 0;
}
Ideally you would upgrade to C++11 and use std::unique_ptr<A> instead of A* as member. But even if you can't do that, consider using boost::scoped_ptr<A>, which will manage the deletion for you (you don't need the destructor) and will make the class non-copyable by default. It also provides better exception-safety to encapsulate allocations in smart pointers like that.
If you need to call method() of type B using base class type A there has to be lookup during the runtime. The lookup is necessary to answer the question: Which method should be called? - the one that corresponds the type in a current line? Or other method in inheritance hierarchy?" If you expect method() from class B to be called when you have pointer or reference to A then you have to create a lookup table. This table is called vtable (from virtual functions table) and it's defined by adding virtual keyword to functions.
#include <iostream>
class A {
public:
virtual ~A(){}
virtual int method() = 0;
protected:
int foo;
};
class B : public A {
public:
B(int bar) { foo = bar; }
int method() {
std::cout << "Calling method() from B" << std::endl;
return foo; }
};
class C {
private:
A* baz;
public:
C(A* faz) { baz = faz; }
A* get() { return baz; }
};
int main(void) {
A* element = new B(1);
C boo(element);
boo.get()->method();
return 0;
}
It prints "Calling method() from B". Please keep in mind that the code is for presentation purposes and it's not good from best practices perspective.

How to add / delete reference to class pointer to/from a vector

The class setup is a bit strange, but it is what it is. I have a problem when I attempt to delete a pointer to a class instance given the following classes:
class Foo {
Foo() { x = 5; }
~Foo() {}
int x;
}
class Bar : public Foo {
Bar() {}
~Bar() {}
void Test() { std::cout << "Hello World! " << x << std::endl; }
}
class Base {
Base() {}
~Base() {}
vector<Foo*> vec;
void Add(Foo* const &f) { vec.push_back(f); }
void Delete() {
delete vec[0];
vec[0] = NULL;
vec.clear();
}
}
class Derived : public Base {
Derived() { b = new Bar(); }
~Derived() {}
AddBar() { Add(b); }
Test() { b->Test(); }
Bar* b;
}
Basically, Derived has a Bar pointer that is dynamically allocated at some point, and is then later passed into an std::vector of Foo pointers, from which Bar is derived. The vector is maintained in a class that Derived inherits from and the vector is used to perform a whole bunch of different actions with all the elements in the vector, but for now I'm showing a single entry.
The problem lies when I try to delete an element from the vector, like below:
int main() {
Derived d;
d.Test(); // works fine, outputs: "Hello World! 5"
d.AddFoo();
d.Test(); // works fine, outputs: "Hello World! 5"
d.Delete();
d.Test(); // doesn't work fine, outputs: "Hellow World! -17891602
}
The memory is freed, seeing how the integer is now garbage data, but d still thinks its Bar* exists, even after deleting it and setting it to NULL in Base.Delete().
Is there a way to have the local Bar* in d be freed/deleted and set to NULL without having to do it from the Derived instance itself ( i.e. have the program crash when it attempts to do the final d.Test() class )?
Technically, I can do that as it is, but it feels messy and inefficient.
Also, if there is a decent answer that doesn't resort to smart or unique pointers, I'd personally prefer that and I'm not going to debate about why.
If that's the only solution, I'm all for it.
Edit: Messed up with Derived::b when I first wrote it, fixed now

A strange access violation error

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.

vector related memory allocation question

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);
};

C++ Seg fault on reference to stored base class pointer

I'm getting some nasty segmentation faults through the g++ compiler on the following code. Any ideas on why this would happen and how to fix it would be great.
#include <iostream>
using namespace std;
class Base {
public:
Base() {}
virtual ~Base() {};
virtual int getNum(int) = 0;
};
class Derived: public Base {
public:
Derived() :
Base() {}
~Derived() {}
int getNum(int num) {
return num;
}
};
class Foo {
public:
Foo() {
};
void init() {
Derived n;
*baseId = n;
}
void otherStuff() {
cout << "The num is" << baseId->getNum(14) << baseId->getNum(15) << baseId->getNum(16) << baseId->getNum(15) << endl;
}
Derived* baseId;
};
int main() {
Foo f;
f.init();
f.otherStuff();
return 0;
}
Here:
void init() {
Derived n;
*baseId = n;
}
the pointer baseId is never initialised, resulting in undefined behaviour when you dereference it. It might be a good idea to explain what you are trying to do here. If you want to maintain a pointer to a Derived or a Base but which starts off pointing to a derived, you can say:
void init() {
baseId = new Derived;
}
but you will then probably need a copy constructor, an assignment operator and a destructor to manage the pointer.
Also, for several reasons, writing an init() function is not normally a good idea - you are better off doing the work directly in the constructor or its initialisation list.
When you call f.init(), the baseId member of Foo is not initialised, yet you dereference it in init(). Are you sure you don't want something more along the lines of:
baseId = new Derived()
void init() {
Derived n;
*baseId = n;
}
Apart from what Neil noted, derived n is local to your init function. It "dies" when you exit the function, so even if you assigned it correctly, it won't work.
What you want is not assigning on the stack but on the heap:
void init() {
baseId = new Derived();
}
or even better:
void init() {
delete baseId;
baseId = new Derived();
}
and a destructor and constructor pair to prevent problems :
Foo() : baseId(0) {};
~Foo() { delete baseId; }
If going for this method, be sure to either block copy constructor and assignment operator, or implement them properly. To implement them however, you'd need to implement copying of Derived too -- or best: use a safe shared_ptr to store the pointer.