Why the output is different from what I expect? - c++

I got a simple program like this:
#include "stdafx.h"
#include <iostream>
using namespace std;
int main()
{
class B {
protected:
int data = 0;
public:
B() { cout << "B() ctor\n";}
virtual ~B() { cout << "~B()\n"; }
virtual void method() { cout << "data in B: " << data << "\n"; }
};
class A : public B
{
int dataA = 2;
public:
A() { cout << "A() ctor\n"; }
~A() { cout << "~A()\n"; }
void method() { cout << "data in A: " << dataA << "\n"; }
};
{
B* fptrList[]{ &B{}, &A{}};
for (auto& itr : fptrList)
itr->method();
}
cin.get();
return 0;
}
Here is a result I expect:
B() ctor
B() ctor
A() ctor
data in B: 0
data in A: 2
~A()
~B()
~B()
Here is the actual result when I ran this program:
B() ctor
~B()
B() ctor
A() ctor
~A()
~B()
data in B: 0
data in B: 0
My questions are:
Why the output is different from what I expect?
How can method() be called after ~A() and ~B() get called?
Why method() of class B get called twice?

This program cannot be explained, because it exhibits undefined behavior.
Translation: it's buggy. It's taking an address of temporary objects, and then attempts to dereference them, after the temporary have been destructed.
A good C++ compiler will even tell you that the program is broken, and will refuse to participate in this disaster:
t.C: In function ‘int main()’:
t.C:26:27: error: taking address of temporary [-fpermissive]
B* fptrList[]{ &B{}, &A{}};
^
t.C:26:33: error: taking address of temporary [-fpermissive]
B* fptrList[]{ &B{}, &A{}};
^
Any output from this program is meaningless garbage.

Here is what's going on:
You initialize fptrList to addresses of temporary variables A and B
The temporary variables get destroyed right after their addresses are taken, so your code has undefined behavior.
Proper way of doing what you are trying to do it is to use operator new with smart pointers, or to make instances outside initializer.
Here is one possible fix:
{
B b;
A a;
B* fptrList[]{ &b, &a };
for (auto& itr : fptrList)
itr->method();
}

Ok, it is undefined behavior, but the question is still interesting why it is this undefined behavior.
Why are constructors/destructors are called in this order? As already established, you creates temporary objects which are created/destroyed one after each other.
Why can I call methods of already non-existent objects? Your temporary object lives at the stack and thus the memory will be freed only at the end of the main function, so you are still able to access this memory and it does not get clobbered by calls to other functions (e.g. printing to the terminal). If you would create the object with new, than delete it and than try to use it - the chances would be higher, that the system has already reclaimed this memory and you would get a segmentation error.
Why I see 2 times the method of B called? This one is funny. To call a virtual function of an object, compiler delegates the decision which method exactly should be called to a virtual table (it's address occupies the first 8 byte of such an object (at least for my compiler and 64bit)). A not that well known details about virtual methods is that during the destructor-call all virtual methods are called as if they were not virtual. But what has it to do with your code? You see its side-effect: The non-virtual behavior is ensured in the destructor by overwriting the virtual table of the current object by the virtual table of the current class. So after the destructor of B is called, the memory contains a virtual table of the class B which you can see, because B::method is called twice.
Let's track the value of the virtual table it in your program:
call of A{}: At first the superclass B-constructor is called - the (not yet fully finished) object has the virtual table of class B (this address is moved into the first 8 byte occupied by the object), than A-constructor is called - now the object has the virtual table of class A.
call of ~A(): after its execution, the destructor of A automatically calls the destructor of B. The first thing the destructor of B does is to overwrite the virtual table of the object with the virtual table of the class B.
So after the destruction the memory is still there and interpreted as an object would have the the virtual table of class B.
itr->method(); finds the virtual table of class B at the address itr points to and calls B::method().

Related

Accessing owner in destructor c++

Say there is an object A which owns an object B via std::unique_ptr<B>. Further B holds a raw pointer(weak) reference to A. Then the destructor of A will invoke the destructor of B, since it owns it.
What will be a safe way to access A in the destructor of B? (since we may also be in the destructor of A).
A safe way me be to explicitly reset the strong reference to B in the destructor of A, so that B is destroyed in a predictable manner, but what's the general best practice?
I'm no language lawyer but I think it is OK. You are treading on dangerous ground and perhaps should rethink your design but if you are careful I think you can just rely on the fact that members are destructed in the reverse order they were declared.
So this is OK
#include <iostream>
struct Noisy {
int i;
~Noisy() { std::cout << "Noisy " << i << " dies!" << "\n"; }
};
struct A;
struct B {
A* parent;
~B();
B(A& a) : parent(&a) {}
};
struct A {
Noisy n1 = {1};
B b;
Noisy n2 = {2};
A() : b(*this) {}
};
B::~B() { std::cout << "B dies. parent->n1.i=" << parent->n1.i << "\n"; }
int main() {
A a;
}
Live demo.
since the members of A are destructed in order n2 then b then n1. But this is not OK
#include <iostream>
struct Noisy {
int i;
~Noisy() { std::cout << "Noisy " << i << " dies!" << "\n"; }
};
struct A;
struct B {
A* parent;
~B();
B(A& a) : parent(&a) {}
};
struct A {
Noisy n1 = {1};
B b;
Noisy n2 = {2};
A() : b(*this) {}
};
B::~B() { std::cout << "B dies. parent->n2.i=" << parent->n2.i << "\n"; }
int main() {
A a;
}
Live demo.
since n2 has already been destroyed by the time B tries to use it.
What will be a safe way to access A in the destructor of B? (since we may also be in the destructor of A).
There isn't safe way:
3.8/1
[...]The lifetime of an object of type T ends when:
— if T is a class type with a non-trivial destructor (12.4), the destructor call starts [...]
I think it's straightforward that you can't access object after it's lifetime has ended.
EDIT: As Chris Drew wrote in comment you can use object after it's destructor started, sorry, my mistake I missed out one important sentence in the standard:
3.8/5
Before the lifetime of an object has started but after the storage which the object will occupy has been
allocated or, after the lifetime of an object has ended and before the storage which the object occupied is
reused or released, any pointer that refers to the storage location where the object will be or was located
may be used but only in limited ways. For an object under construction or destruction, see 12.7. Otherwise,
such a pointer refers to allocated storage (3.7.4.2), and using the pointer as if the pointer were of type void*,
is well-defined. Such a pointer may be dereferenced but the resulting lvalue may only be used in limited
ways, as described below. The program has undefined behavior if:
[...]
In 12.7 there is list of things you can do during construction and destruction, some of the most important:
12.7/3:
To explicitly or implicitly convert a pointer (a glvalue) referring to an object of class X to a pointer (reference)
to a direct or indirect base class B of X, the construction of X and the construction of all of its direct or
indirect bases that directly or indirectly derive from B shall have started and the destruction of these classes shall not have completed, otherwise the conversion results in undefined behavior. To form a pointer to (or
access the value of) a direct non-static member of an object obj, the construction of obj shall have started
and its destruction shall not have completed, otherwise the computation of the pointer value (or accessing
the member value) results in undefined behavior.
12.7/4
Member functions, including virtual functions (10.3), can be called during construction or destruction (12.6.2).
When a virtual function is called directly or indirectly from a constructor or from a destructor, including
during the construction or destruction of the class’s non-static data members, and the object to which the
call applies is the object (call it x) under construction or destruction, the function called is the final overrider
in the constructor’s or destructor’s class and not one overriding it in a more-derived class. If the virtual
function call uses an explicit class member access (5.2.5) and the object expression refers to the complete
object of x or one of that object’s base class subobjects but not x or one of its base class subobjects, the
behavior is undefined.
As has already been mentioned there is no "safe way". In fact as has been pointed out by PcAF the lifetime of A has already ended by the time you reach B's destructor.
I also just want to point out that this is actually a good thing! There has to be a strict order in which objects get destroyed.
Now what you should do is tell B beforehand that A is about to get destructed.
It is as simple as
void ~A( void ) {
b->detach_from_me_i_am_about_to_get_destructed( this );
}
Passing the this pointer might be necessary or not depending on the design ob B (If B holds many references, it might need to know which one to detach. If it only holds one, the this pointer is superfluous).
Just make sure that appropriate member functions are private, so that the interface only can be used in the intended way.
Remark:
This is a simple light-weight solution that is fine if you yourself completely control the communication between A and B. Do not under any circumstances design this to be a network protocol! That will require a lot more safety fences.
Consider this:
struct b
{
b()
{
cout << "b()" << endl;
}
~b()
{
cout << "~b()" << endl;
}
};
struct a
{
b ob;
a()
{
cout << "a()" << endl;
}
~a()
{
cout << "~a()" << endl;
}
};
int main()
{
a oa;
}
//Output:
b()
a()
~a()
~b()
"Then the destructor of A will invoke the destructor of B, since it owns it." This is not the correct way of invocation of destructors in case of composite objects. If you see above example then, first a gets destroyed and then b gets destroyed. a's destructor won't invoke b's destructor so that the control would return back to a's destructor.
"What will be a safe way to access A in the destructor of B?". As per above example a is already destroyed therefore a cannot be accessed in b's destructor.
"since we may also be in the destructor of A).". This is not correct. Again, when the control goes out of a's destructor then only control enters b's destructor.
Destructor is a member-function of a class T. Once the control goes out of destructor, the class T cannot be accessed. All the data-members of class T can be accessed in class T's constructors and destructor as per above example.
If you look only on the relations of the two classes A and B, the construction is well:
class A {
B son;
A(): B(this) {}
};
class B {
A* parent;
B(A* myparent): parent(myparent) {}
~B() {
// do not use parent->... because parent's lifetime may be over
parent = NULL; // always safe
}
}
The problems arise, if objects of A and B are proliferated to other program units. Then you should use the tools from std::memory like std::shared_ptr or std:weak_ptr.

Deleting polymorphic objects and memory leaks

Suppose I have a class A and a class B which inherits from A.
Then I do something like:
A* a = new B();
delete a;
Why a memory leak happens only when there is a dynamic memory allocation within B?
How C++ knows to remove the "B part" when there is dynamic memory allocations within B but fails where it is?
[Update:]
How does the following code does not result in a memory leak: [I suspect it to be undefined behaviour, but I don't really understand anything :(]
#include <iostream>
using std::cout;
using std::endl;
class A {
public:
virtual void f() {
cout << "1" << endl;
}
~A() {
cout<< "A A'tor" << endl;
}
};
class B : public A {
private:
public:
B(){}
~B(){
cout<< "B D'tor" << endl;
}
void f() {
cout << "2" << endl;
}
};
int main() {
A* a = new B();
//a->f();
delete a;
return 0;
}
While compiler sees statement "delete a;"
It knows only static type of "a" is pointer to A, if there is no virtual destructor in class A. As a result wrong destructor gets called leading to memory leak
If there is a virtual destructor in class A
then compiler comes to know that Dynamic type of "a" is pointer to B and there will a vtable from where it will get B's destructor address at run time
This is because the destructor isn't virtual. If there is ever a chance in your program to delete derived class objects via base class pointers, you should define a virtual destructor in the base class. This will allow B's destructor to get called first, allowing you to free any dynamic memory B may have allocated. A's destructor will get called after B's.
Another good rule of thumb is to train yourself to think about making your destructor virtual anytime you make a method virtual. Since the motivation to make a method virtual means you will be calling methods on base class pointers, it follows that you will likely be deleting objects through base class pointers.

C++ Debug Assertion Fails Only With VPTR

I'm wondering why I get an exception on the delete part in one case here, but not in the other.
No exception case
#include <iostream>
using namespace std;
class A
{
public:
~A() { cout << "A dtor" << endl; }
};
class B : public A
{
public:
int x;
~B() { cout << "B dtor" << endl; }
};
A* f() { return new B; }
int _tmain(int argc, _TCHAR* argv[])
{
cout << sizeof(B) << " " << sizeof(A) << endl;
A* bptr= f();
delete bptr;
}
Herethe output is 4 1 .. A dtor, since A has 1 byte for identity and B has 4 because of int x.
Exception case
#include <iostream>
using namespace std;
class A
{
public:
~A() { cout << "A dtor" << endl; }
};
class B : public A
{
public:
virtual ~B() { cout << "B dtor" << endl; }
};
A* f() { return new B; }
int _tmain(int argc, _TCHAR* argv[])
{
cout << sizeof(B) << " " << sizeof(A) << endl;
A* bptr= f();
delete bptr;
}
Here the output is 4 1 .. A dtor, since A has 1 byte for identity and B has 4 because of the vptr that's needed for its virtual destructor.
But then a debug assertion fails inside the delete call (_BLOCK_TYPE_IS_VALID).
Environment
I'm running Windows 7 with Visual Studio 2010 SP1Rel.
See this post
A quick summary:
You are telling the machine to delete an instance of A
As this is a class which we call through pointer/reference maybe we should use a virtual table (VT)?
There is no virtual members in A thus no VT is used
We call the standard destructor of A…
Bang! We are trying to delete class A but it happens that the pointer
has lead us to object of B which contains VT which A didn't know of.
sizeof(A) is 1 (as AFAIK it’s not legal to have size equal 0) and
sizeof(B) is 4 (due to presence of VT). We wish to delete 1 byte, but
there is a block of 4 bytes. Due to DEBUG heap monitoring, the error
was caught.
The solution of course is to declare the base class's (A's) dtor as virtual so B's dtor will always be called.
EDIT: For the first case, here's what the standard has to say:
§5.3 In the first alternative (delete object), if the static type of the object to be deleted is different from its
dynamic type, the static type shall be a base class of the dynamic type of the object to be deleted and the
static type shall have a virtual destructor or the behavior is undefined. In the second alternative (delete
array) if the dynamic type of the object to be deleted differs from its static type, the behavior is undefined.
So both cases lead us to the realm of undefined behavior which of course differs from one implementation to the other. But it stands to reason that for most implementations the first case is easier to handle or at least easier to contemplate than the second which is just an esoteric anti-pattern.
As others have pointed out, you are deleting an object whose static type is different from its dynamic type, and since the static type doesn't have a virtual destructor, you get undefined behavior. This includes the behavior of sometimes working and sometimes not working as you are seeing. However, I think you are interested in a little deeper understanding of what is happening with your particular compiler.
Class A has no members at all, so its data layout ends up looking like this:
struct A {
};
Since class B derives from class A, class A becomes embedded within B. When class B has no virtual functions, the layout ends up looking like this:
struct B {
A __a_part;
int x;
};
The compiler can convert a B* to an A* by just taking the address of __a_part, as if the compiler had a function like this:
A* convertToAPointer(B* bp) { return &bp->__a_part; }
Since __a_part is the first member of B, the B* and the A* point to the same address.
Code like this:
A* bptr = new B;
delete bptr;
Is effectively doing something like this:
// Allocate a new B
void* vp1 = allocateMemory(sizeof(B));
B* bp = static_cast<B*>(vp1);
bp->B(); // assume for a second that this was a legal way to construct
// Convert the B* to an A*
A* bptr = &bp->__a_part;
// Deallocate the A*
void* vp2 = ap;
deallocateMemory(vp2);
In this case, vp2 and vp1 are the same. The system is allocating and deallocating the same memory address, so the program runs without an error.
When class B has a virtual member function (the destructor in this case). The compiler adds a virtual table pointer, so class B ends up looking like this:
struct B {
B_vtable* __vptr;
A __a_part;
};
The issue here is that __a_part is no longer the first member, and the convertToAPointer operation will now change the address of the pointer, so vp2 and vp1 no longer point to the same address. Since a different memory location is being deallocated than the one that was allocated, you get the error.

What's the issue with malloc() and virtual functions? [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
C++: why is new needed?
Why cant I use malloc to allocate space for my objects when they are children of a class containing virtual functions? This is really frustrating. Is there a good reason?
The following program illustrates the problem. It segfaults on line 27, where I call aa->f()
#include <iostream>
#include <cstdlib>
class A
{
public:
virtual int f() {return 1;}
};
class B
{
public:
int f() {return 1;}
};
class Aa : public A {};
class Bb : public B {};
int main()
{
Aa* aa = (Aa*)malloc(sizeof(Aa));
Aa* aan = (Aa*)new Aa();
Bb* bb = (Bb*)malloc(sizeof(Bb));
std::cout << bb->f() << std::endl;
std::cout << aan->f() << std::endl;
std::cout << aa->f() << std::endl;
return 0;
}
Version info: g++ (Ubuntu/Linaro 4.4.4-14ubuntu5) 4.4.5
A common way to implement virtual functions is to have a pointer to a "virtual table" or vtable at a negative offset from the object. This table is needed to figure out what virtual function to call. This is why just malloc'ing space doesn't work.
malloc only allocates memory, but does not create an object. So, the line
Aa* aa = (Aa*)malloc(sizeof(Aa));
allocates a region of memory that is large enough to hold an A, but contains garbage. As others pointed out, this also means that the pointer to the vtable will not be set (I got that one from #David Rodríguez's comment on another answer), which is required to dispatch calls to virtual functions. Since B does not contain virtual functions, no such problem arises. It would happen with B too, however, if B contained any data-members that require initialization, such as this:
class B
{
public:
B() : foo(new int()) {}
int f() {return *foo;}
private:
int * foo;
};
The line
Aa* aan = (Aa*)new Aa();
can do without the cast:
Aa* aan = new Aa();
The reason is that malloc knows nothing about C++ constuctors and consequently does not call them. You can call the constuctors yourself using placement new:
int main()
{
Aa* aa = (Aa*)malloc(sizeof(Aa));
new(aa)Aa;
Aa* aan = (Aa*)new Aa();
Bb* bb = (Bb*)malloc(sizeof(Bb));
new(bb)Bb;
std::cout << bb->f() << std::endl;
std::cout << aan->f() << std::endl;
std::cout << aa->f() << std::endl;
aa->~Aa();
free(aa);
delete aan;
bb->~Bb();
free(bb);
return 0;
}
Note that you have to manually call the destructors before freeing such memory.
Don't use malloc, use new - malloc does not call constructors.
When you do A * a = new A(); the compiler will allocate memory, set up the vtable pointer for A and call the constructor. When you call a virtual function, the vtable is used to actually find the function.
When you do A * a = (A *) malloc(...); the compiler will allocate memory, which will contain random data. When you call a virtual function, it'll look at the (garbage) vtable and call some random location.
A class with virtual functions look something like this internally:
struct Foo {
void * vtable;
int aClassMemberVar;
};
Calling a virtual function looks at the "hidden" vtable pointer, which points to the class vtable, a linked list of pointers to functions. So this vtable pointer must be initialized, and malloc doesn't do that.
Surely because the Virtual Function Table isn't getting created properly?
malloc does not call the constructor of the class, so your object is not initailized properly, hence it seg faults. Use new to allocate memory when using C++. BTW, there is no need to cast the pointer returned from new.
The good reason is called virtual tables. Objects of types that have virtual methods have a table of pointers pointing to the address of the actual virtual methods to be called. These are called virtual tables or v-tables.

c++: following piece of code crashes

#include <iostream>
using namespace std;
class B
{
public:
B() { cout << "Base B()" << endl; }
~B() { cout << "Base ~B()" << endl; }
private:
int x;
};
class D : public B
{
public:
D() { cout << "Derived D()" << endl; }
virtual ~D() { cout << "Derived ~D()" << endl; }
};
int
main ( void )
{
B* b = new D;
delete b;
}
---- output----------
Base B()
Derived D()
Base ~B()
*** glibc detected *** ./a.out: free(): invalid pointer: 0x0930500c ***
======= Backtrace: =========
/lib/tls/i686/cmov/libc.so.6[0xb7d41604]
/lib/tls/i686/cmov/libc.so.6(cfree+0x96)[0xb7d435b6]
/usr/lib/libstdc++.so.6(_ZdlPv+0x21)[0xb7f24231]
./a.out[0x8048948]
/lib/tls/i686/cmov/libc.so.6(__libc_start_main+0xe5)[0xb7ce8775]
./a.out[0x80487c1]
Aborted
If i remove the private member "int x" from the base class, it works fine
The destructor for the base class B must be virtual too.
class B doesn't have a virtual destructor and you try to delete an instance of class D derived from class B through a pointer to class B - that's undefined behavior. You have to make class B destructor virtual to make your code work.
What you are doing is UB, but for the specific compiler you are using behavior can be described as follows. To ease the ASCII-graphics below, modifying the example, adding a y member to D and modifying main.
#include <iostream>
using namespace std;
class B
{
public:
B() { cout << "Base B()" << endl; }
~B() { cout << "Base ~B()" << endl; }
private:
int x;
};
class D : public B
{
public:
D() { cout << "Derived D()" << endl; }
virtual ~D() { cout << "Derived ~D()" << endl; }
private:
int y; // added.
};
int
main ( void )
{
D* d = new D; // modified.
B* b = d;
delete b;
}
In the compiler you are using, the vtable, if any, is placed in the beginning of the memory block.
In the compiler you are using the memory layout for this is as follows:
+--------+
| vtable | <--- d points here, at the start of the memory block.
+--------+
| x | <--- b points here, in the middle of the memory block.
+--------+
| y |
+--------+
Later when calling delete b the program will try to free the memory block using the b pointer, which points to the middle of the memory block.
This will in turn result in the crash due to the invalid pointer error.
An alternative answer may be to use boost::shared_ptr : its templated constructors will remember that your object is of type D.
#include <boost/shared_ptr.hpp>
int
main ( void )
{
boost::shared_ptr<B> b( new D );
}
The above modification of your code will work fine, even without a virtual destructor.
By the way, unless you want to store pointers to D, there is no use in making D's destructor virtual.
Well, if you don't want a virtual destructor, then you must delete the object with a pointer to it's actual type:
int
main ( void )
{
D* as_d = new D;
B *as_b = as_d;
// you can use the object via either as_b or as_d but
// you must delete it via as_d
delete as_d;
}
That said, if you are not careful, it can be easy to delete the object through the wrong pointer.
So I know you don't want it, but for your own sanity, just make the B destructor virtual.
When you destroy derived class object using base class pointer then , it will lead to partial destruction of the object( ( only base class constructor is invoked ) if base class ctor is not virtual.
so you must make base class desrtuctor as virtual.
When a class is purely non virtual, it does not have an entry for the VPTR. Therefore B is exactly 4 bytes.
Here is an illustration of the memory. VPTR is at the smallest memory location. This is so that all derived classes know where to find the VPTR. Hence, D is 8 bytes, the first 4 is VPTR, and the next 4 for x.
But, isn't D is-a B? No, it works in the same way as multiple inheritance. When you assign a D address into a B pointer, the compiler knows that, and instead of giving you the REAL address of D, it gives you the address offsetted so that it works like a B. In this case, its really offset by 4 bytes. So when you try to B->x, you get the right value.
When you pass this offset address back to the heap in free, everything goes crazy, because what it needs is the original address. This behavior is not undefined. It happens when in multiple inheritance as well.
I think the fact of being the integer member causing a memory crash, it's just a matter of "luck". I mean, if your destructor in the base class isn't virtual, the "destruction" of D isn't called.
So, in memory, your object D in the heaps could look like:
Object D
+-----------+
| B subobj. |
+-----------+
| D members |
+-----------+
If the B's destructor isn't virtual and if you delete a pointer base to B, the D part isn't destructed. In your case, the D part has size 0, and the B part a size of sizeof(int) (4 bytes), and that makes the situation a little more complicated to "guess", but perhaps you compiler is adding additional information for any reason to your objects in memory.
So, after the deletion of b, but before the end of the application, perhaps some piece of code adding by the compiler at exit time is causing the crash because of your unpropertly deletion of b (reusing of this part of memory for example or something like that).
Since your code is very short, you could inspect the behaviour of your code with 'gdb', at assembly level, in the interval between the deletion of b and the termination of your code.