-2

Suppose I have a function that performs some task. The function returns a pointer to an int. My question is this: do I have to deallocate memory or is this general format okay?


int *do_something()
{
    int *local{ new int };
    //do_something_here

    return local;
    delete local;
}

int main()
{
   int *result{ new int };

   result = do_something();
   delete result;
   return 0;
}
  • 2
    You need to call `delete` for ***every*** `new` you have in your code. Note that `delete local;` after the return statement won't have any effect. – πάντα ῥεῖ Mar 25 '19 at 17:14
  • First, it depends on how you got the pointer in the first place. Second, nothing after a `return` matters because it will never be reached. If it's a pointer to something allocated with `new` you must eventually `delete` it. – François Andrieux Mar 25 '19 at 17:14
  • This is a template. I'm not sharing what may turn out to be proprietary code. – Sir know-a-ton Mar 25 '19 at 17:15
  • 1
    @Sirknow-a-ton With all due respect, nobody wants to copy your code (specially if it contains functions that return `new`ed pointers) we just want a representative example. See [MCVE]. – François Andrieux Mar 25 '19 at 17:16
  • you should not be returning a newed `int` in the first place. Doing so is like placing pitfalls in your code, sooner or later you will regret it – 463035818_is_not_a_number Mar 25 '19 at 17:16
  • Why issue this: `int *result{ new int };`, which allocates memory, and then later assign a value to result?? – Gardener Mar 25 '19 at 17:17
  • @Sirknow-a-ton Note that the objected pointed to by `result` will be leaked since the pointer is assigned to before it's original value is `delete`d. – François Andrieux Mar 25 '19 at 17:17
  • WAIT so how do I return a pointer AND deallocate the memory? – Sir know-a-ton Mar 25 '19 at 17:17
  • @Sirknow-a-ton You can't do both, at least not from the context of a function. Use a smart pointer like [`std::unique_ptr`](https://en.cppreference.com/w/cpp/memory/unique_ptr) instead. – François Andrieux Mar 25 '19 at 17:18
  • please fix your example, I think it adds a bit of confusion that it is not 100% clear if the function returns an `int` or an `int*` – 463035818_is_not_a_number Mar 25 '19 at 17:18
  • You can't *correctly* return a pointer-to-int from an int return, you would need `int* do_something()` for this to even be legal. As πάντα ῥεῖ says, one `delete` for every `new`. The thread/object that takes ownership of that `new` memory should be the one that does the `delete`ing. It is up to the programmer to make it *explicitly* clear to anyone who looks at their code where any memory allocation is owned. – Tzalumen Mar 25 '19 at 17:20
  • @Sirknow-a-ton It's conceptually not possible. The pointer would then point to a deleted object and be useless. You only `delete` something when you're done with it. If you return it form a function it usually implies that you aren't done with it or you wouldn't need to return it in the first place. – François Andrieux Mar 25 '19 at 17:20
  • Well your int function returns an int and not an int pointer. Also you can't follow a return with a delete. The function goes out of scope once you hit the return. If needed you could free up that allocated memory later using the pointer you returned. – Wollzy Mar 25 '19 at 17:20
  • Thankfully with modern `c++` the use of `new` is discouraged. – drescherjm Mar 25 '19 at 17:24
  • @drescherjm From what I understand I'm supposed to use it? Aren't I supposed to say, "make room for a variable of this type" so that I can do something with it later? – Sir know-a-ton Mar 25 '19 at 17:27
  • @Sirknow-a-ton `make_unique` (together with smart pointers) is supposed to be used instead. – SergeyA Mar 25 '19 at 17:29
  • What I was trying to say is there are better methods that are in `c++11` (2011 standard) and above that remove the need for using `new` in most situations. The better methods are less error prone and easier to use. – drescherjm Mar 25 '19 at 17:31
  • @drescherjm what version of c++ are they on now? – Sir know-a-ton Mar 25 '19 at 17:32
  • `c++17` with `c++20` in the process of being standardized. Every 3 years there is a new/updated standard. – drescherjm Mar 25 '19 at 17:33
  • https://en.wikipedia.org/wiki/C%2B%2B20 – drescherjm Mar 25 '19 at 17:48
  • Functions don't 'require' the delete (nonsequitor?), but maybe your team's coding standard does. The C++ language has no 'requirement' that prevents you from new'ing an object instance in one function and deleting the instance in another. The compilers do not detect and will not 'warn' or 'err' if you should do so. It is not undefined behaviour to do so. Also, there is no 'requirement' that every new has a corresponding delete. – 2785528 Mar 25 '19 at 17:57
  • Also, cppreference.com Has essentially the entirety of the C++ standard from C++98 to C++20 available in a (mostly) readable format with examples. – Tzalumen Mar 25 '19 at 18:14
  • Do you teach? You mean I can declare space in some function A and delete the space in another function B without passing the new'ed object into B? Obviously there is no 'requirement' but if you want to prevent a memory leak then you need to deallocate the space taken up somehow. – Sir know-a-ton Mar 25 '19 at 18:19
  • @Sirknow-a-ton _"You mean I can declare space in some function A and delete the space in another function B without passing the new'ed object into B?"_ You must have been misunderstanding something. Of course you'll need to keep track of a pointer that was achieved by the use of `new` to call `delete` properly. – πάντα ῥεῖ Mar 25 '19 at 21:02

2 Answers2

5

To document the transfer of object ownership and to prevent memory leaks, you should return objects allocated on the heap using unique_ptr. This is C++ best practice.

For more details, see C++ Core Guidelines: Never transfer ownership by a raw pointer (T*) or reference (T&):

Reason

If there is any doubt whether the caller or the callee owns an object, leaks or premature destruction will occur.

alter igel
  • 5,696
  • 3
  • 16
  • 38
Maxim Egorushkin
  • 119,842
  • 14
  • 147
  • 239
  • Or `shared_ptr`. – Tzalumen Mar 25 '19 at 17:22
  • 2
    @Tzalumen In my experience, in 99% of cases `shared_ptr` is used to avoid thinking of ownership, leading to sub-optimal designs and cyclic references. So, I would recommend sticking with `unique_ptr`, if possible. – Maxim Egorushkin Mar 25 '19 at 17:25
  • 1
    @Tzalumen I would argue that most of the time there would be no need to return `shared_ptr` from the creator type of function. – SergeyA Mar 25 '19 at 17:25
0

My question is this: do I have to deallocate memory or is this general format okay?

Yes, you do have to deallocate memory if you allocated memory dynamically. Otherwise you risk the memory use of your program to grow uncontrollably and consume all available memory - or at least consume more than is necessary.

Do functions that return pointers require that I delete the value that is returned?

Just because a function returns a pointer, doesn't necessarily mean that it must be deleted. An example:

int* a_function(int* ptr) {
    return ptr + 1;
}

int main() {
    int arr[2];
    int* iptr = a_function(arr);
    // must not delete iptr
}

A function can require the caller to delete the returned pointer. It appears that your do_something example function is such function. This is a very bad design for a function. If the ownership of an allocation is transferred to the caller, then a smart pointer should be used instead.


return local;
delete local;

It is pointless to have statements after returning. They will never be executed.

int *result{ new int };
result = do_something();

Here, you lose the value returned by new-expression. As a consequence, it is no longer possible to delete that value - the later delete deletes the new value instead. Such loss of a pointer value and consequent inability to deallocate the memory is called a memory leak.

eerorika
  • 181,943
  • 10
  • 144
  • 256
  • So lets say I have some program P with a memory leak. It will compile despite having the leak. What does the memory leak do then? Is it that addresses are left full and thus we have less memory down the road? I'm assuming that allowing memory addresses to be un-emptied results in there being no memory to be used later on, am I correct? I'm not reading a book I'm just teaching myself. – Sir know-a-ton Mar 25 '19 at 17:31
  • @Sirknow-a-ton The consequence of a memory leak is that you cannot deallocate the memory. If you do this repeatedly (usually, programs tend to call functions more than once), then each allocation uses more and more memory. Computers do not have infinite memory, and it will eventually run out. – eerorika Mar 25 '19 at 17:35
  • Wait so does that mean if am running code with memory leaks in it then my laptop will have addresses that weren't deallocated? Or does my OS handle that? – Sir know-a-ton Mar 25 '19 at 17:41
  • @Sirknow-a-ton Your OS will give your program more memory as long as there is memory available. Once memory runs out, your OS will terminate programs until memory is available. Unless you're unlucky, OS probably chooses your leaky program for termination. – eerorika Mar 25 '19 at 17:45
  • 1
    @Sirknow-a-ton Practical operating systems reclaim all of the memory it provided to a process when that process ends. So a leak is only a problem while the problematic program runs. – François Andrieux Mar 25 '19 at 17:59