Is overriding destructor for automatic object well defined? - c++

I had a situation where I wanted to import a call after another call from the calling function. I decided to override a virtual destructor for the purpose:
#include <iostream>
struct type {
virtual ~type() {
std::cout << "ordinary" << std::endl;
}
void method() {
struct method_called : type {
virtual ~method_called() override {
std::cout << "method called" << std::endl;
}
};
this->~type();
new (this) method_called{};
}
};
int main() {
std::cout << "ordinary expected" << std::endl;
{
type obj;
}
std::cout << "method expected" << std::endl;
{
type obj;
obj.method();
}
std::cout << "method expected" << std::endl;
type* pobj = new type{};
pobj->method();
delete pobj;
}
It seems the overridden destructor is called only using dynamic allocation. Is this intended?
GCC godbolt.

this->~type();
Any dereference of any pointer pointing to the object or variable referring to the object that exists prior to this line is undefined behavior once you do this.
This includes the automatic storage destructor.
To avoid undefined behaviour in main after doing this, you'd have to call exit or similarly never return from the scope where the variable exists.
By the time the destructor is finished, the objects lifetime is over. Almost any use of the object after that triggers UB. You can reuse the storage:
new (this) method_called{};
This creates an distinct object in the storage that this refers to. If this storage has sufficient alignment and size, doing so is fine. It is extremely tricky to get right, because one of the few ways to safely get a pointer to this newly created object is by recording the return value to placement new like this:
auto* pmc = new (this) method_called{};
you don't do that.
{
type obj;
obj.method();
}
this is undefined behavior. The standard does not restrict what the program produced by your compiler does if this code is or would be executed at any point in your programs execution.
type* pobj = new type{};
pobj->method();
delete pobj;
so is this.

Related

Is it well defined to recreate an object using its base class? [duplicate]

I had a situation where I wanted to import a call after another call from the calling function. I decided to override a virtual destructor for the purpose:
#include <iostream>
struct type {
virtual ~type() {
std::cout << "ordinary" << std::endl;
}
void method() {
struct method_called : type {
virtual ~method_called() override {
std::cout << "method called" << std::endl;
}
};
this->~type();
new (this) method_called{};
}
};
int main() {
std::cout << "ordinary expected" << std::endl;
{
type obj;
}
std::cout << "method expected" << std::endl;
{
type obj;
obj.method();
}
std::cout << "method expected" << std::endl;
type* pobj = new type{};
pobj->method();
delete pobj;
}
It seems the overridden destructor is called only using dynamic allocation. Is this intended?
GCC godbolt.
this->~type();
Any dereference of any pointer pointing to the object or variable referring to the object that exists prior to this line is undefined behavior once you do this.
This includes the automatic storage destructor.
To avoid undefined behaviour in main after doing this, you'd have to call exit or similarly never return from the scope where the variable exists.
By the time the destructor is finished, the objects lifetime is over. Almost any use of the object after that triggers UB. You can reuse the storage:
new (this) method_called{};
This creates an distinct object in the storage that this refers to. If this storage has sufficient alignment and size, doing so is fine. It is extremely tricky to get right, because one of the few ways to safely get a pointer to this newly created object is by recording the return value to placement new like this:
auto* pmc = new (this) method_called{};
you don't do that.
{
type obj;
obj.method();
}
this is undefined behavior. The standard does not restrict what the program produced by your compiler does if this code is or would be executed at any point in your programs execution.
type* pobj = new type{};
pobj->method();
delete pobj;
so is this.

Providing a pointer of an object to a constructor causes object to be destructed [duplicate]

This question already has answers here:
What is The Rule of Three?
(8 answers)
Closed 5 years ago.
I'm seeing a strange behavior in one of my projects. The circumstances are as follows:
I have an object. Let's call Victim, which contains a pointer variable, a constructor and destructor.
I have another object, let's call Perpetrator, whose constructor accepts a Victim object, and copies the pointer variable to a concrete variable inside.
I create a Victim*, and create the object with new, then supply this to Perpetrator via Perpetrator(*victim).
When the Perpetrator's constructor finishes, Victim's destructor is called and object is deleted.
The problem is the only copy of the Victim, which is poor is completely destroyed during the construction process. Tidying up the program at the end via delete poor will cause a double-free error.
The behavior is consistent in C++98/11, GCC 4.8.5, 7.x, and LLVM CLANG, hence it must be well defined. What is this behavior is called, and what are the semantics of it?
My theory is, since the constructor accepts a concrete object, it's considered copied, so it's destructed when the constructor / function is done.
Since I praise PoC||GTFO, here's the code:
Clarification: The example is written intentionally, since it's a simplified model of a much more complex, but non-leaky and well-managed data structure complex. Removing all necessary bits made it look like an horribly broken code. In the real code Victim is a long living data store and Perpetrator is an interim storage variable used for processing said data.
#include <iostream>
using namespace std;
struct Victim
{
double* pointer;
Victim ()
{
this->pointer = new double(42.2);
}
~Victim ()
{
cout << "Destructor of the Victim is called." << endl;
delete this->pointer;
}
};
struct Perpetrator
{
double concrete;
Perpetrator (Victim victim)
{
concrete = *(victim.pointer);
}
};
int main ()
{
Victim* poor = new Victim();
Perpetrator cruel(*poor);
cout << cruel.concrete << endl;
}
Sample output:
./destructor_test
Destructor of the Victim is called.
42.2
Perpetrator (Victim victim) - is passing an object by value. Means it has to be (copy) constructed, and then destructed when the call finishes.
As a matter of fact, there is no need to use new at all. This:
int main ()
{
Victim poor;
Perpetrator cruel(poor);
cout << cruel.concrete << endl;
}
Acts similarly. You'll see two constructions, and two destructions. The second one your original code doesn't exhibit, because your example leaks.
pass Victim by ref:
struct Perpetrator
{
double concrete;
Perpetrator (Victim& victim)
{
concrete = *(victim.pointer);
}
};
Victim will construct & destruct once each.
Is this what you want to achive?
using namespace std;
struct Victim
{
double* pointer;
Victim ()
{
this->pointer = new double(42.2);
}
~Victim ()
{
cout << "Destructor of the Victim is called." << endl;
delete this->pointer;
}
};
struct Perpetrator
{
double concrete;
Perpetrator (Victim *victim)
{
concrete = *(victim->pointer);
}
~Perpetrator ()
{
cout << "Destructor of the Perpetrator is called." << endl;
}
};
int main ()
{
Victim* poor = new Victim();
Perpetrator cruel(poor);
cout << cruel.concrete << endl;
delete poor;
}
output:
42.2
Destructor of the Victim is called.
Destructor of the Perpetrator is called.

C++ creating object with *new

I have a method with my custom object as a parameter:
void processObject(Myobject instance)
{
//some code using instance
}
I'm calling method above from another method like this:
...
processObject(*new MyObject());
...
Could this cause a memory leak? Should I call something like delete &instance in my process object method?
Thanks a lot for your help!
EDIT
ok now I know that there is memory leak, what would you suggest as the easiest way to fix this? My idea is to change this code:
void processObject(Myobject* instance)
{
//some code using instance
delete instance;
}
...
processObject(new MyObject());
...
I need as easy and fast way to fix this as possible (same issue in the code on many many places).
You can not delete the instance object that the processObject procedure receives, because it is a copy of the object you created with new. Imagine it like that:
You create a new object using new, this creates the object on the heap and gives you a MyObject*
You dereference the pointer, therefore you have an object of type MyObject. Here you also lose the pointer, as you don't store it anywhere
You pass the object to the processObject method, and as the signature of that function states, a copy of your object is created and passed to the function
As you have lost the pointer, you can not delete it anymore.
A solution would be not allocating the object with new and passing a refrence to the process method:
void processObject(MyObject& ref) {
// do something with the reference
}
void test() {
MyObject x;
processObject(x);
// do stuff with x
}
Or allocating it with new and doing this:
void processObject(MyObject* ptr) {
// do something with the pointer
}
void test() {
MyObject* x = new MyObject();
processObject(x);
// do stuff with x
delete x;
}
Yes, you should delete after a new, but you can not delete this newly created object.
Whenever you write *new x;, you are dereferencing a pointer into an actual reference (or object).
In your case, Myobject is passed by value and is thus copied, leaving your pointer not within stack space and thus causing a memory leak.
I suggest you use the following calling procedure with nearly the same effect: (without the memory leak):
processObject(MyObject());
I think you may have gotten the new syntax from Java, where we are forced to use it. In C++, you can simply call the constructor implicitly like this and have a new object be constructed in-place, which is then passed as function argument.
In this case the object is constructed on the stack and thereby has automatic storage duration (no memory leak).
As it stands it will memory leak. You could delete the object inside the processObject function by taking the address, however the signature
void processObject(Myobject instance)
doesn't prevent someone from passing a local variable/stack object.
Myobject instance;
processObject(instance);
If this happens you can't delete the object.
Avoid using raw pointers, and avoid confusing users of your function.
Try:
class MyObject
{
public:
MyObject() { std::cout << "Reporting construction of object (ptr: " << (int)this << ")\n"; }
MyObject(const MyObject & other) { std::cout << "Reporting copy-construction of object (ptr: " << (int)this << ")\n"; }
MyObject(MyObject && other) { std::cout << "Reporting move-construction of object (ptr: " << (int)this << ")\n"; }
virtual ~MyObject() { std::cout << "Reporting destruction of object (ptr: " << (int)this << ")\n"; }
};
void DoSomething(MyObject obj)
{
}
int main()
{
DoSomething(*new MyObject());
}
Result:
Reporting construction of object (ptr: 140173320)
Reporting copy-construction of object (ptr: -1078250292)
Reporting destruction of object (ptr: -1078250292)
As you see, first instance was not destroyed - thus leaked.

c++ destroy an object on stack frame

I try to understand what happen when an object destroy on stack.
here is my sample code:
#include <stdio.h>
struct B {
~B() {puts("BBBB");}
};
int main()
{
B b;
b.~B();
}
output is
BBBB
BBBB
based on the output, I can tell the object is destroy twice.one is ~B(), another one is after "}". how and why can a object get destroy twice?
update:
after i review replies, I think the destructor doesnt destroy this object. it there a way to destroy an object before it reach out of scope "}".
Thanks
You are not supposed to invoke the destructor by hand. What's happening is you are invoking the destructor and then when the object gets popped off the stack the destructor is called again automatically by the compiler.
~B() is called before the destruction
Destructors are usually used to deallocate memory and do other cleanup
for a class object and its class members when the object is destroyed.
A destructor is called for a class object when that object passes out
of scope or is explicitly deleted.
Source
So you are just calling a function twice.
There's minimal-to-no garbage collection in C++, objects are simply destroyed when they go out of scope. So you could replace your test to this:
#include <iostream>
struct B {
B() { std::cout << "B()" << std::endl; }
~B() { std::cout << "~B()" << std::endl; }
};
int main()
{
std::cout << "start main" << std::endl;
{ // scope
std::cout << "start scope" << std::endl;
B b;
std::cout << "end scope" << std::endl;
} // <-- b gets destroyed here.
std::cout << "end main" << std::endl;
}
If you want an object on the stack over which you have control over the lifetime of, you can do something like this:
#include <iostream>
#include <memory.h>
struct B {
B() { std::cout << "B()" << std::endl; }
~B() { std::cout << "~B()" << std::endl; }
};
int main()
{
std::cout << "start main" << std::endl;
{ // scope
std::cout << "start scope" << std::endl;
void* stackStorage = alloca(sizeof(B));
std::cout << "alloca'd" << std::endl;
// use "in-place new" to construct an instance of B
// at the address pointed to by stackStorage.
B* b = new (stackStorage) B();
std::cout << "ctord" << std::endl;
b->~B(); // <-- we're responsible for dtoring this object.
std::cout << "end scope" << std::endl;
} // <-- b gets destroyed here, but it's just a pointer.
std::cout << "end main" << std::endl;
}
Live demo: http://ideone.com/ziNjkd
Remember, though, it's the stack. When it goes out of scope, it goes away - if you don't destroy it, it just dissapears.
{
void* stackStorage = alloca(sizeof(B));
B* b = new (stackStorage) B(); // "in-place new"
} // (*b)s memory is released but (*b) was not dtord.
The only time you would manually call a destructor is when you've got grounds to use placement new
Keep in mind that the destructor is like any other function. The only difference with other function is that it is automatically called when the object is deallocated. You cann see this like an event. You get a chance to clean everything before the object get annihilated. Calling the destructor by hand does not deallocate the object.
Object construction/destruction in C++ follows this simple rule:
Anything automatically allocated (and constructed) is automatically destructed.
Anything explicitely allocated with new is explicitely destructed via delete.
Anything explicitely constructed with new() must be explicitely destructed by calling the destructor.
The destructor has to be called in all three cases, the difference is in how the memory for the object is allocated:
The object is on the stack, its allocation is managed by the compiler.
The object is on the heap, its allocation is managed by the programmer.
The object is anywhere, construction and destruction is independent of allocation.
In the first two cases, we have a combination of allocation and construction, and consequently a combination of destruction and deallocation. The third case is entirely different, but fully supported by the language, and the reason that you are allowed to explicitely call a destructor; because in this case an object is constructed without allocating memory for it. Consequently, it must be destructible without deallocating memory as well. This case can be used like this:
void* buffer = (void*)new char[sizeof(Foo)]; //allocation
Foo* myFoo = new(buffer) Foo(); //construction
myFoo->~Foo(); //destruction
Foo* anotherFoo = new(buffer) Foo(); //reuse the buffer to construct another object in it
anotherFoo->~Foo(); //destruction of the second object
delete buffer; //deallocation
Note, that this actually constructs two objects, one after the other in the same place, destructing them explicitely before the memory is reused. The buffer could also be a large slap of memory to store many objects, std::vector<> works like this.
So, yes, destruction does destroy your object, you must not use it after destruction. But since you used an automatically allocated and constructed object in your question, the compiler also took care of destructing it, leading to the double destruction. This is always a bug, objects must never be destructed twice, but the language allows you to do it anyway.
What you are doing is a pretty good example of a variable running out of scope.
int main()
{
//Main is started
B b;
/* What happens is that `b` is constructed as a local
variable and put on the runtime stack.*/
b.~B();
/*You then invoke the destructor manually which is bad practice.
But it is possible and it will execute the code.
However, the state of the resulting instance is undefined.*/
}
/*Main ends and local variables defined in the
current scope get destroyed. Which also means that B's destructor
is called the second time */
FYI - the only time you are supposed to do manual destruction of an object is when it is put on the heap like this:
// create an instance of B on the heap
B* b = new B();
// remove instance and implicitly call b's destructor.
delete b;
i would like to answer my own question.
after a lot of reading, Here is my summary.
1. destructor doesnt destroy it's object. the object stays at stack
until out of scope.
2. nothing can destroy a stack object.
3. the destructor did destroy RESOURCE inside the object.
sample code:
struct B {
B() {happy="today is a good day"; hour = 7;}
~B() {puts("BBBB");}
std::string happy;
int hour;
};
int main()
{
B b;
std::cout << b.happy << b.hour <<std::endl;
b.~B();
std::cout << b.happy << b.hour <<std::endl;
}
output:
today is a good day7
BBBB
7
BBBB
we can see a resource b.happy is gone after b.~B() is called. this is a proof of my point 3.
you see the b.hour(int type is not a resource) is still here. this is a proof of my point 1.

c++ allocation on the stack acting curiously

Curious things with g++ (maybe also with other compilers?):
struct Object {
Object() { std::cout << "hey "; }
~Object() { std::cout << "hoy!" << std::endl; }
};
int main(int argc, char* argv[])
{
{
Object myObjectOnTheStack();
}
std::cout << "===========" << std::endl;
{
Object();
}
std::cout << "===========" << std::endl;
{
Object* object = new Object();
delete object;
}
}
Compied with g++:
===========
hey hoy!
===========
hey hoy!
The first type of allocation does not construct the object. What am I missing?
The first type of construction is not actually constructing the object. In order to create an object on the stack using the default constructor, you must omit the ()'s
Object myObjectOnTheStack;
Your current style of definition instead declares a function named myObjectOnTheStack which returns an Object.
Yet another example of the "most vexing parse". Instead of defining an object, you've declared a function named myObjectOnTheStack that takes no arguments and returns an Object.
Object myObjectOnTheStack();
is a forward declaration of a function myObjectOnTheStack taking no parameters and returning an Object.
What you want is
Object myObjectOnTheStack;