Can somebody explain why I'm getting this error after program ends?
free(): invalid pointer
This is my code:
#include <iostream>
#include <memory>
int main()
{
int a = 3;
std::unique_ptr<int> up(&a);
std::cout << a << std::endl;
std::cout << *up << std::endl;
std::cout << &a << std::endl;
std::cout << up.get() << std::endl;
return 0;
}
std::unique_ptr<int> up(&a);
The whole and entire purpose of std::unique_ptr, the only reason it exists, is so that when it goes out of scope and gets destroyed it automatically deletes whatever it's pointing to (assuming that it hasn't been moved from).
a was instantiated in function local scope, and not dynamic scope, hence attempting to delete, what was not newed, results in undefined behavior, and your crash.
This is a toy model of a unique pointer:
struct toy_ptr {
int* p;
~toy_ptr() { delete p; }
};
("toy" because much more is needed, while this is only what is needed to reproduce your problem)
Now if you do this:
int main() {
int a = 0;
toy_ptr ptr{&a};
}
the toy_ptr takes ownership of a. Owning an object means: the toy_ptr is responsible for deleting it in its destructor. a was not allocated via new, hence attempting to delete it via delete &a invokes undefined behavior.
A unique_ptr is not a toy_ptr, but it also does take ownership of the pointer passed to the constructor and it does attempt to delete it in its destructor.
Related
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.
Why if I write a code like this (X is a generic class) calling constructor and destructor
int main()
{
X one ();
one.~X();
return 0;
}
give me this error?
Double free() or corruption:C++
You should almost never call destructors explicitly, they are called implicitly when an object falls out of scope (or deleted, if allocated on heap). First you manually deallocate background's array by calling background.~Y(), and next this same array tries to get deallocated once more at the next }.
Calling the destructor of an object is almost always wrong. Actually I never came across a situation where this was right. You need to read about RAII and maybe this example will help you to understand why you get the error:
#include <iostream>
struct Foo{
Foo() { std::cout << " constructor " << std::endl; }
~Foo() { std::cout << " destructor " << std::endl; }
};
int main(){
Foo foo;
// foo.~Foo(); // <- never ever do this !
} // <- object is destroyed here !
Run this and you will see, that the destructor is called already. Destroying an already destroyed object leads to the error you get.
I want to do something like this:
unique_ptr<MyObj> MyFunc() {
MyObj* ptr = new MyObj();
...
return unique_ptr<MyObj>(ptr);
}
unique_ptr<MyObj> value = MyFunc();
But I'm unsure if the object will be deleted when the temporary value was destructed after the function returns. If so, how should I implement correctly a function that returns a unique_ptr?
No, the object will not be deleted when function scope ends. This is because move constructor of unique_ptr will 'move' the ownership semantics to the new unique_ptr object, and destruction of the old unique_ptr will not cause deletion of the allocated object.
Note: This is not the right way of doing this. If there is an exception thrown between the point of memory allocation and unique_ptr<> creation you will have a memory leak.
Although the code can compile and work, it is the best to work with std::make_unique directly:
return std::make_unique<T>(/* your arguments*/);
your snippet can create some problems such as:
new can throw std::bad_alloc if no memory available
MyObj can throw an exception
ptr can get lost in the way until it is assigned to the unique_ptr
The way to allocate the pointer is std::make_unique. There are similar functions for the other types of smart pointers as well, e.g. std::make_shared.
If you want to return it from a function, you should use std::move, since unique_ptrs don't like to be copied.
Return it like this: return std::move(ptr);
If nothing goes wrong, your code should work; the original object will be created within the MyFunc function and its ownership will be transferred back to the caller. However, the best way to create a std::unique_ptr is with std::create_unique (to avoid possible leaks upon intervening error conditions). You can verify that this happens correctly with either a debugger or some console output; My expansion/modification of your code (shown below) produces the following output, verifying that only one object is created and it is destroyed at the end of main):
Created
999
Destroyed
Here's the code:
#include <iostream>
#include <memory>
class MyObj
{
public:
MyObj( int v )
: value( v )
{
std::cout << "Created" << std::endl;
}
~MyObj()
{
std::cout << "Destroyed" << std::endl;
}
int value;
};
std::unique_ptr<MyObj> MyFunc()
{
auto ptr = std::make_unique<MyObj>( 999 );
// ...do other stuff here?...
// return std::move( ptr ); // Loki Astari says move() is unnecessary
return ptr;
}
int main()
{
auto p = MyFunc();
std::cout << p->value << std::endl;
return 0;
}
I was experimenting with using unique_ptr and wrote some simple code to check how it works with move semantics.
#include <iostream>
#include <vector>
using namespace std;
class X
{
public:
X(){}
~X() { cout << "Destructor X" << endl; }
void Print() { cout << "X" << endl; }
};
int main()
{
unique_ptr<X> ptr(new X());
ptr->Print();
vector<unique_ptr<X>> v;
v.push_back(move(ptr));
ptr->Print();
v.front()->Print();
return 0;
}
The output is as follows:
X
X
X
Destructor X
My expectation was that the original unique_ptr ptr would be invalidated after the push_back. But the Print() method is called just fine. What would be the explanation for this behavior?
My expectation was that the original unique_ptr ptr would be invalidated after the push_back.
It's set to a null pointer. You can check that by comparing it to nullptr.
But the Print() method is called just fine. What would be the explanation for this behavior?
You're calling a member function on a null pointer, which is undefined behaviour. That member function doesn't actually access any data in the class, so it doesn't crash, but it's still undefined behaviour.
You get similar behaviour for this program, it has nothing to do with unique_ptr:
int main()
{
X x;
X* ptr = &x;
ptr->Print();
ptr = nullptr;
ptr->Print();
}
It appears to work fine because X::Print() doesn't actually read anything from the this pointer. If you change the definition of X::Print() to access some member data in the class you'll probably get a crash due to dereferencing a null pointer.
See When does invoking a member function on a null instance result in undefined behavior? for more information.
What you have is plain undefined behavior. If I replace the contents of main with the following
int main()
{
unique_ptr<X> ptr;
ptr->Print();
cout << (static_cast<bool>(ptr) ? "active\n" : "inactive\n");
}
Both gcc and clang still print
X
inactive
You're calling a member function on a nullptr, and I'm guessing it just happens to work because the member function doesn't actually make use of the this pointer. Change your class definition to:
class X
{
int y = 0;
public:
X(){}
~X() { cout << "Destructor X" << endl; }
void Print() { cout << "y = " << y << endl; }
};
Now your original code should result in a segmentation fault because it'll attempt to dereference nullptr.
As for your expectation that unique_ptr will be invalidated after you move from it, you're absolutely correct. This is guaranteed by the standard.
§20.8.1/4 [unique.ptr]
Additionally, u can, upon request, transfer ownership to another unique pointer u2. Upon completion of such a transfer, the following postconditions hold:
— u2.p is equal to the pre-transfer u.p,
— u.p is equal to nullptr, and
...
Above u & u2 are unique_ptr objects, and p is the pointer to the managed object.
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.