0

If I write:

b = new int;
b = new int; 
delete b;

I know that delete b; only deletes the second b from memory. Since there is nothing pointing to the first b after this delete, there is memory leak.

In such case, I know that there's a way to recover this leak in C# and Java. Is there a way to recover this memory leak in C++?

trincot
  • 317,000
  • 35
  • 244
  • 286
John Park
  • 335
  • 5
  • 23
  • Not while adhering to Standard C++. Once you lose the last reference to a dynamic allocation, you're hosed. – user4581301 Mar 25 '19 at 03:59
  • @user4581301 I see. Thanks. – John Park Mar 25 '19 at 04:39
  • No worries. The take-away is avoid raw dynamic allocation. Use [containers](https://en.cppreference.com/w/cpp/container) and [smart pointers](https://en.cppreference.com/w/cpp/memory) to handle the memory for you. If you can't, wrap the allocation with [RAII](https://stackoverflow.com/questions/2321511/what-is-meant-by-resource-acquisition-is-initialization-raii) and observe the [Rule of Three or Five](https://en.cppreference.com/w/cpp/language/rule_of_three). – user4581301 Mar 25 '19 at 04:45
  • The deletion of the "second `b`" isn't what causes the "first `b`" to be leaked. The second assignment of `b = new int` is what does that, whether followed by `delete b` or not. The `delete b` simply releases the result of the second `new` expression. – Peter Mar 25 '19 at 04:50
  • @user4581301 Right. I really need to get more comfortable with using smart pointers. I think one of my professors talked about it as well. – John Park Mar 25 '19 at 05:21
  • @Peter Thanks for the clarification. That actually makes a lot more sense. – John Park Mar 25 '19 at 05:24

2 Answers2

1

Option 1.

The easiest way is to avoid new and delete altogether.

Instead of:

b = new int;
b = new int; 
delete b;

Write:

std::unique_ptr<int> b;
...
b = std::make_unique<int>();
b = std::make_unique<int>(); 

When b is overwritten, or gets out of scope, it frees the memory. No delete is required or even allowed. Note quite like the Java garbage collector, but good enough most of the time.

Option 2.

Another way is to use an add-on garbage collector, but that solution is not advisable. First, the garbage collector is conservative meaning that there is a probability to have a memory leak despite the garbage collector. Second, these solutions tend to make existing problems worse, since the memory leaks will not be noticed and treated when introduced. Treating memory leaks a year after introduction is orders of magnitude more difficult than to treat them an hour after introduction.

NOTE: Using unique_ptr is not as safe as in garbage-collected languages such as C#,Java, and Python. It fails when there is no clear ownership model and when there is a circular ownership. If element a has a unique_ptr to b and b has a unique_ptr to a then they will never be freed. They will never be freed since a unique_ptr frees the object in the destructor, but nobody will call the destructor of neither a nor b. If nobody calls the destructor, then the unique_ptr will never delete the object, and never call the destructor of the other object.

NOTE 2: Sometimes std::shared_ptr should be used instead of unique_ptr, but that does not solve the issue of circular references. This only solves the issue of multiple-owners of a single object.

NOTE 3: These smart pointers do not lower the possibility of stack-overflow due to deep recursion in destructors. This is likely to happen in recursive destruction of long linked-lists or in unbalanced binary-trees. Using unique_ptr for this cases simply hides the fact that recursion is taking place.

Michael Veksler
  • 8,217
  • 1
  • 20
  • 33
  • Ok I see. So in C++, there seems to be no absolutely definitive alternative to adhering to the conventional practice of being mindful of how we dynamically allocate memory and how we can go about in safeguarding a way to clear the memory once we are done using the data at the end of our program. Thank you for your detailed explanation. – John Park Mar 25 '19 at 05:17
  • @JohnPark yes, but there is a lot of automation. All you have to be mindful about, most of the time, is who owns what. You rarely have to think about who allocates and who frees stuff. All this as long as you avoid new/malloc – Michael Veksler Mar 25 '19 at 05:32
0

I know that there is a way to recover this memory leak in C# and Java

Java and C# are both garbage collecting languages so they don't tend to have memory leaks often (its almost impossible), but when they do you can throw an exception,

Is there a way to recover this memory leak in C++?

in c++ memory leaks are more common because you are manually allocating memory every time you create a pointer, so you would always throw an exception to point out if a memory leak where to occur, where it is and, how to deal with it...so the answer to your question is...no you cant recover from a memory leak in c++, its a "Down To The Metal" language which is why its so vulnerable if not written correctly, but you can always throw an exception for when a memory leak does occur you can pin point it and see how to fix it.