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.
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.
Here is my program:
#include <iostream>
using namespace std;
class Object {
public:
Object() { cout << "Object constructor!" << endl; }
~Object() { cout << "Object destructor!" << endl; }
Object(const Object& obj) { information = obj.information; cout << "Copy constructor!" << endl; }
void setInformation(const string info) { information = info; }
string getInformation() const { return information; }
private:
string information;
};
class Storage {
public:
Storage() { object = static_cast<Object*>(operator new(sizeof(Object))); }
~Storage() { operator delete(object); }
void setObject(const Object& obj) {
// Todo: assign obj to the allocated space of the pointer object
}
private:
Object* object;
};
int main()
{
Object o;
o.setInformation("Engine");
Storage storage;
storage.setObject(o);
return 0;
}
In Storage I am allocating space to store one object of type Object without creating it. I am using placement new for that which allocates a memory, and freeing it in the destructor. I know that I can use
object = new(object) Object()
to construct an object. But can I put in the memory an object that is already created? In my case call method setObject(). If yes what problems I can encounter with such memory management? Thanks in advance.
The simplest way to achieve the behavior you are trying to implement would be to use std::optional from C++17. It will allow you to "reserve" the memory for your Object without constructing it and without using the heap. It will also handle all the constructor and destructor calls.
This also can be done without std::optional, but you will essentially have to implement a similar solution yourself. In any case you will need an additional member to specify whether object constructed or not, so you can properly handle the destruction and assignment.
Then your setObject method will look something like this:
void setObject(const Object& obj) {
if (constructed) {
*object = obj;
} else {
new (object) Object(obj);
constructed = true;
}
}
To make use of move semantics you can modify your method like this:
void setObject(Object obj) {
if (constructed) {
*object = std::move(obj);
} else {
new (object) Object(std::move(obj));
constructed = true;
}
}
Note that now setObject accepts it parameter by-value so it can be used with both lvalue and rvalue references to construct the parameter which is then will be moved into the member.
Placement new is a pretty advanced construct, and the thought of having an Object* that actually points to uninitialized memory is rather terrifying. May I suggest you make your life easier?
class Storage {
void setObject(const Object& obj) {
if (object) {
*object = obj;
} else {
object.reset(new Object(obj));
}
}
private:
std::unique_ptr<Object> object;
};
This requires a copy constructor and assignment operator on the Object class, but is much more idiomatic C++. And in the Object implementation as shown, the default, compiler-provided implementations are already fine.
Just to clarify:
But can I put in the memory an object that is already created?
No, you cannot. There is no way how to move objects in memory in C++. For trivially copyable types, you can copy (e.g, by memcpy or memmove) their memory representations. But this actually does not move anything. Moreover, your Object class is not trivially copyable.
What you can move is the contents of objects, which is what move semantics is for.
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 thinking that when a function returns an object on the stack to the calling function, the calling function gets a copy of the original object but the original object's destructor is called as soon as the stack unwinds. But in the following program, the destructor is getting called only once. I expected it to be called twice.
#include <iostream>
class MyClass
{
public:
~MyClass() { std::cout << "destructor of MyClass" << std::endl; }
};
MyClass getMyClass()
{
MyClass obj = MyClass();
return obj; // dtor call for obj here?
}
int main()
{
MyClass myobj = getMyClass();
return 0; // Another dtor call for myobj.
}
But "destructor of MyClass" is getting printed only once. Is my assumption wrong or is there something else going on here?
This is a special case where the compiler is allowed to optimize out the copy: this is called named return value optimization (NRVO). Basically, the compiler allocates memory for the return object on the call site and lets the function fill in that memory directly instead of creating the object at the called site and copying it back. Modern compilers do this routinely whenever possible (there are some situations where this isn't easy since there are several return paths in the function that return different instances).
I have a Foo object, and a std::list holding instances of it. My problem is that when I add a new instance to the list, it first calls the ctor but then also the dtor. And then the dtor on another instance (according to the this pointer).
A single instance is added to the list but since its dtor (along with its parents) is called, the object cant be used as expected.
Heres some simplified code to illustrate the problem:
#include <iostream>
#include <list>
class Foo
{
public:
Foo()
{
int breakpoint = 0;
}
~Foo()
{
int breakpoint = 0;
}
};
int main()
{
std::list<Foo> li;
li.push_back(Foo());
}
When you push_back() your Foo object, the object is copied to the list's internal data structures, therefore the Dtor and the Ctor of another instance are called.
All standard STL container types in C++ take their items by value, therefore copying them as needed. For example, whenever a vector needs to grow, it is possible that all values in the vector get copied.
Maybe you want to store pointers instead of objects in the list. By doing that, only the pointers get copied instead of the object. But, by doing so, you have to make sure to delete the objects once you are done:
for (std::list<Foo*>::iterator it = list.begin(); it != list.end(); ++it) {
delete *it;
}
list.clear();
Alternatively, you can try to use some kind of 'smart pointer' class, for example from the Boost libraries.
You are creating a temporary Foo here:
li.push_back( Foo() )
push_back copies that Foo into its internal data structures. The temporary Foo is destroyed after push_back has been executed, which will call the destructor.
You will need a proper copy constructor that increases some reference count on the class members that you do not want to destroy early -- or make it private to force yourself on the pointer solution.
Use this object to understand:
class Foo
{
public:
Foo(int x): m_x(x)
{
std::cout << "Constructed Object: " << m_x << ")\n";
}
Foo(Foo const& c): m_x(c.m_x+100)
{
std::cout << "Copied Object: " << m_x << ")\n";
}
~Foo()
{
std::cout << "Destroyed Object: " << m_x << ")\n";
}
};
The First main
std::list<Foo*> li;
li.push_back(Foo(1));
Here we create a temporary Foo object and call push_back(). The temporary object gets copied into the list and the function returns. On completion of this statement the temporary object is then destroyed (via the destructor). When the list is destroyed it will also destroy all the obejcts it contains (Foo is an object with a destructor so destruction includes calling the destructor).
So you should see somthing like this:
Constructed Object: 1
Constructed Object: 101
DestroyedObject: 1
DestroyedObject: 101
In the second example you have:
std::list<Foo*> li;
li.push_back(new Foo(1));
Here you dynamically create an object on the heap. Then call the push_back(). Here the pointer is copied into the list (the pointer has no constructor/destructor) so nothing else happens. The list now contains a pointer to the object on the heap. When the function returns nothing else is done. When the list is destroyed it destroys (note the subtle difference betweens destroy and delete) the object it contains (a pointer) but a pointer has no destructor so nothing happens any you will leak memory.
So you should see somthing like this:
Constructed Object: 1
What actually happens here is that you store a copy of the passed object in the list, because you're sending it by value instead of by reference. So the first dtor that is called is actually called on the object you pass to the push_back method, but a new instance had been created by then and it is now stored in the list.
If you don't want a copy of the Foo object to be created, store pointers to Foo objects in the list instead of the objects themselves. Of course when doing it you will have to properly release memory on destruction of the list.
Making the list holding pointers instead of instances solves the problem with the destructor being called. But I still want to understand why it happens.
#include <iostream>
#include <list>
class Foo
{
public:
Foo()
{
int breakpoint = 0;
}
~Foo()
{
int breakpoint = 0;
}
};
int main()
{
std::list<Foo*> li;
li.push_back(new Foo());
}