Why is there no memory leak here - c++

I was trying to answer this question, so I decided to create the following simple test case so that the OP could see by himself the memory leak.
#include<iostream>
class MyObject
{
public:
MyObject(){std::cout << "creation of my object" << std::endl;}
virtual ~MyObject(){std::cout << "destruction of my object" << std::endl;}
};
void processMyObject(MyObject foo)
{
}
int main()
{
processMyObject(*new MyObject());
return 0;
}
I compiled it :
g++ test.cpp -o test
And then, I saw an unexpected output :
creation of my object
destruction of my object
I have absolutly no idea of what is happening here. Could anyone explain to me ?
PS: I used g++ 4.6.3

Since you pass an object by value to the function, you incurr a copy or move-copy construction. But you are not keeping track of that with your primitive memory leak checker. You could provide your own copy constructor, and then you will see two objects are being created, and only one is being destroyed:
#include<iostream>
class MyObject
{
public:
MyObject() {std::cout << "creation of my object" << std::endl;}
MyObject(const MyObject&) {std::cout << "copy creation of my object" << std::endl;}
~MyObject() {std::cout << "destruction of my object" << std::endl;}
};
void processMyObject(MyObject foo) {}
int main()
{
processMyObject(*new MyObject());
}
Output:
creation of my object
copy creation of my object
destruction of my object

Because you're taking the MyObject by value.
Thus there is a destruction. But it is the destruction of the foo argument at the end of processMyObject.
The *new does actually still leak in this case.
EDIT: As pointed out by juanchopanza, you need to also print a statement in the copy constructor and in the move constructor as well.

What happens in your code
You construct an object and get information about it (creation of my object)
You pass it to function - copy constructor fires, but does not report anything
The copy is destroyed - you get information about it (destruction of my object)
The original instance leaks despite fact, that you don't have any information about it.
How to see it?
Simply report pointers to this during construction and destruction (quick'n'dirty, please don't complain):
class MyObject
{
public:
MyObject(){std::cout << "creation of my object (" << (int)this << ")" << std::endl;}
virtual ~MyObject(){std::cout << "destruction of my object (" << (int)this << ")" << std::endl;}
};
Result:
creation of my object (165437448)
destruction of my object (-1076708692)
As you see, destroyed object is different than created one.
How to "fix" it to show the leak?
The simplest way to "fix" your code is to pass object by pointer:
#include<iostream>
class MyObject
{
public:
MyObject(){std::cout << "creation of my object" << std::endl;}
virtual ~MyObject(){std::cout << "destruction of my object" << std::endl;}
};
void processMyObject(MyObject * foo)
{
}
int main()
{
processMyObject(new MyObject());
return 0;
}
Another option is to report copy ctors and move ctors as well:
class MyObject
{
public:
MyObject(){std::cout << "creation of my object" << std::endl;}
MyObject(const MyObject & obj) { std::cout << "copy-ctor" << std::endl; }
MyObject(MyObject && obj) { std::cout << "move-ctor" << std::endl; }
virtual ~MyObject(){std::cout << "destruction of my object" << std::endl;}
};

There actually is a memory leak. Just because your object was destroyed, doesn't mean that you deleted the resources you acquired with new. You have to explicitly use delete.
EDIT
So here's what's happening:
You are calling the default constructor on the fly, and passing it to the function call. This prints the first message.
As part of the function call, the object is passing to processMyObject(), creating a new object in that scope using the copy constructor, which has been implicitly defined by the compiler.
When that object (in processMyObject()) goes out of scope, its destructor is called, printing the second message.
So, the instance printing the first message is different from that printing the second one.
Hope that clears things up.

Related

Why std::move doesn't avoid a second destruction?

I know ordinary std::vector::push_back() will copy the object. I hope this code would only destruct a only once, using std::move() and A(A&&) noexcept to avoid copying. But it doesn't seem to work.
Is there any way that I can construct an object before push_back() and move it into a vector perfectly?
#include <bits/stdc++.h>
using namespace std;
class A {
public:
A() { std::cout << "construct" << this << '\n'; }
A(A&&) noexcept { std::cout << "move" << this << "\n"; }
A(const A&) = delete;
~A() { std::cout << "destruct" << this << '\n'; }
};
std::vector<A> as;
void add(A&& a) {
std::cout << "add 1\n";
as.push_back(std::move(a));
std::cout << "add 2\n";
}
int main() {
add(A());
std::cout << "main2\n";
return 0;
}
Output:
construct0x16d20b1fb
add 1
move0x151e068b0
add 2
destruct0x16d20b1fb
main2
destruct0x151e068b0
I hope this code would only destruct a only once, using std::move() and A(A&&) noexcept to avoid copying.
Using Move constructor perverts copying but doesn't prevent creating new objects, you are creating an inline object with default constructor "cout : construct0x16d20b1fb" and then from that object's data your going to create a 'NEW' object and calling move constructor will
transform the ownership of the object's data/resources to the new object that is being 'Constructed' so that explain the "cout : move0x151e068b0" then the line is finished so your inline object is destroyed "cout " destruct0x16d20b1fb" then your program finishes "cout : destruct0x151e068b0" your object that made via move constructor is destroyed.
you are expecting the behavior of pointers from your vector of "Objects" which is supposed to hold actual objects not pointer to other objects so it needs to containt objects and each of objects that are in that vector has a different address, unless you create your object and use a vector pointers to objects.
By the way std::move is but a cast, it casts to rvalue references so when you are capturing with rvalue reference there's no need to cast it again, you should be using it like this:
A a_object1;
vector.push_back(std::move(a_object1));
and it will use the move constructor. although in this case it will cast it implicitly because you are capturing only by rvalue reference in add function unless you add an overload to this function that also takes reference there's no need.

c++ - Destructor called on assignment

I'm still learning the basics of c++ so I may not have had the correct vocabulary to find the answer to my question but I couldn't find this mentioned anywhere.
If I have a class with a constructor and destructor why does the destructor get called on the new data when I am assigning to the class?
For example:
#include <iostream>
class TestClass {
public:
int* some_data;
TestClass() {
std::cout << "Creating" << std::endl;
some_data = (int*)malloc(10*sizeof(int));
}
~TestClass() {
std::cout << "Deconstructing" << std::endl;
free(some_data);
}
TestClass(const TestClass& t) : some_data{t.some_data} {
std::cout << "Copy" << std::endl;
}
};
int main() {
TestClass foo;
std::cout << "Created once" << std::endl;
foo = TestClass();
std::cout << "Created twice" << std::endl;
}
which prints:
Creating
Created once
Creating
Deconstructing
Created twice
Deconstructing
free(): double free detected in tcache 2
Aborted (core dumped)
So after following this in the debugger it appears the deconstructor is called on the newly created data which is confusing to me. Shouldn't the original data be freed once and then at the end of execution the new data should be freed? It seems like the original data is never freed like this.
Your object owns a raw pointer to allocated memory, but does not implement a proper copy constructor that makes an allocation and copies the data behind the pointer. As written, when you copy an object, the pointer is copied, such that now two objects point to the same address (and the old one that the just-assigned-to object is leaked.)
When the temporary goes out of scope, it deletes its pointer but the copy (foo) still points to it. When foo goes out of scope, it deletes the same pointer again, causing this double free error you're seeing.
If you need to write a destructor to clean up, you almost always need to also provide copy and assignment operations, or disable them.
SUGGESTIONS:
hold the pointer in a std::unique_ptr which will fail to compile if you try to copy it. This forces you to deal with the issue. Also, malloc and free are mainly for C or low-level C++ memory management. Consider using new and delete for allocations instead. (unique_ptr uses delete by default, not free, and you must not mix them.)
alternately, delete the copy constructor and assignment operator
also, consider when you want to move from an xvalue (temporary or moved lvalue), you can pilfer the allocation from the right-hand-side. So this class is a good candidate for move constructor and move assignment.
Most of the comments and a few details more in code:
#include <iostream>
#include <array>
#include <memory>
class TestClass
{
// members of a class should not be public
private:
// TestClass owns the data, this is best modeled
// with a unique_ptr. std::array is a nicer way of
// working with arrays as objects (with size!)
std::unique_ptr<std::array<int, 10>> some_data;
public:
TestClass() :
some_data{ std::make_unique<std::array<int,10>>() }
{
std::cout << "Creating" << std::endl;
// set everything in the array to 0
std::fill(some_data->begin(), some_data->end(), 0);
}
~TestClass()
{
std::cout << "Destructing" << std::endl;
// no need to manually delete a std::unique_ptr
// its destructor will free the memory
// and that will be called as part of this destructor
}
TestClass(const TestClass& t) :
// when you copy a class the copy should have its
// own copy of the data (to avoid deleting some data twice)
// or you must chose shared ownership (lookup std::shared_ptr)
some_data{ std::make_unique<std::array<int,10>>() }
{
std::cout << "Copy" << std::endl;
// copy data from t to this instances array
// (note this would not have been necessary
// it your array was just a non-pointer member,
// try that for yourself too.)
std::copy(some_data->begin(), some_data->end(), t.some_data->begin());
}
TestClass(TestClass&& rhs) :
some_data{ std::move(rhs.some_data) } // transfer ownership of the unique_pointer to this copy
{
std::cout << "Move" << std::endl;
}
// Important this assignement operator is used in your original code too
// but you couldn't see it!
TestClass& operator=(const TestClass& t)
{
some_data = std::make_unique<std::array<int, 10>>();
std::copy(some_data->begin(), some_data->end(), t.some_data->begin());
std::cout << "Assignment" << std::endl;
return *this;
}
};
int main()
{
TestClass foo;
std::cout << "Created once" << std::endl;
foo = TestClass();
std::cout << "Created twice" << std::endl;
TestClass bar{ std::move(foo) };
std::cout << "Moved" << std::endl;
}

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.

Understanding C++ heap/stack allocations when passing dereferenced pointer by reference

I am trying to understand what happens with object creation and destruction in this example.
#include <iostream>
class Person {
public:
const int name;
Person() = delete;
Person(int& name) : name(name) {
std::cout << "Person " << name << " created" << std::endl;
}
Person(const int& name) : name(name) {
std::cout << "Person " << name << " created -- copy constructor" << std::endl;
};
~Person() {
std::cout << "Person " << name << " destroyed" << std::endl;
}
};
class Family {
public:
Person mom, dad;
Family() = delete;
Family(Person& m, Person& d) : mom(m), dad(d) {
std::cout << "Family created" << std::endl;
};
Family(const Person& m, const Person& d) : mom(m), dad(d) {
std::cout << "Family created -- copy constructor" << std::endl;
};
~Family() {
std::cout << "Family destroyed" << std::endl;
}
};
int main()
{
Person* m = new Person(1);
Person* d = new Person(2);
Family f(*m, *d);
return 0;
}
This outputs
Person 1 created -- copy constructor
Person 2 created -- copy constructor
Family created
Family destroyed
Person 2 destroyed
Person 1 destroyed
So I am not entirely sure how to interpret this. I've been taught that anything I heap-allocate using the new keyword should subsequently be delete-d. And stack variables are lost when the object moves out of scope. My understanding is like this. If instead of accepting Person& m by reference I took it without the &, like Person m, then m would be copied here (on the stack) and I'd have a memory leak because the heap-allocated new Person("Jane") would never be deleted.
But since I am taking it by reference, do I still have a memory leak? Both m and d have their destructors called, but does this also free the heap-memory? And how can I think of Family.dad? Is this a stack variable? If so, then is the entire Family considered a scope?
I am quite confused by this example and don't really know how to reason about it. Also, do I still have a memory leak here since I never explicitly delete the two Person objects?
Add copy-constructor to see the whole picture.
Although Family::Family gets the objects by reference, it then copies them into the members mom and dad. So the destructor invocations you observe actually occur when those members get destructed.
The original objects are not freed - until the program exits.
As for the location of Person instances you create using new - they are allocated in the "free store", as per C++ Standard. Typically, it means they reside on the heap.
OTOH, Family instance (along with all its members) has an "automatic storage". With most of popular compilers/platforms, this means it's allocated on the stack.

Lifetime of objects in c++

class Entity
{
public:
int a;
Entity(int t)
:a(t)
{
std::cout << "Constructor !" << std::endl;
}
~Entity()
{
std::cout << "Destructor !" << std::endl;
}
Entity(Entity& o)
{
std::cout << "Copied !" << std::endl;
this->a = o.a;
}
};
Entity hi()
{
Entity oi(3);
return oi;
}
int main()
{
{
Entity o(1);
o = hi();
}
std::cin.get();
}
OUTPUT:
Constructor !
Constructor !
Copied !
Destructor !
Destructor !
Destructor !
I created two objects and I copied one, So three constructors and three destructors.
Your "Copied!" line in the output is coming from the copy constructor, so you're creating three objects, not just two (then you're destroying all three, as expected).
Note that a copy constructor should normally take its argument by const reference. At a guess, you may be using Microsoft's C++ compiler, which will bind a temporary to a non-const reference.
Also note that if you turn on optimization, you can probably expect to see just two constructors and two destructors, with no copy construction happening. With a new enough (C++17) compiler, that should happen even if you don't turn on optimization (copy elision has become mandatory).
This is a trivial question
Can any one explain the reason for three destructor?
when you call
o=hi();
your function is called which makes an object of type Entity , which in return calls the constructor.
This is where you get one extra constructor message
Replace your Entity(int t) contructor by this
Entity(int t)
:a(t)
{
std::cout << "Constructor created with integer "<< a << std::endl;
}
You will see which constructors were called when you run the code.