1

I came across an issue today regarding local variables. I learned that...

 int * somefunc()
 {
     int x = 5;
     return &x;
 }

 int * y = somefunc();
 //do something

is bad, unsafe, etc. I'd imagine that the case is the same for...

int * somefunc()
{
    int * x = new int;
    x = 5;
    return x;
}

int * y = somefunc();
//do something
delete y;

I've been under the impression for the longest time that this would be safe as the address of x stays in scope when it's returned. However, I'm having second thoughts now and I'm thinking this would lead to memory leaks and other problems, just as the fist example would. Can someone confirm this for me?

MGZero
  • 5,812
  • 5
  • 29
  • 46
  • 2
    No, this is fine but prefer smart pointers to `new/delete` when possible. That way you minimize the likelihood of leaks and clean up your code. – Steve Townsend Jun 22 '11 at 19:21
  • 5
    The second is fine except for `x = 5;`. That should be `*x = 5;`. That and I agree with Steve about smart pointers. – Fred Larson Jun 22 '11 at 19:22

8 Answers8

8

As it stands, the second example is wrong. You probably meant this:

int * somefunc()
{
    int * x = new int;
    *x = 5; // note the dereferencing of x here
    return x;
}

Now this is technically fine, but it is prone to errors. First, if after the allocation of x an exception happens, you have to catch it, delete x and then rethrow, or you get a memory-leak. Second, if you return a pointer, the caller has to delete it - callers forget.

The recommended way would be to return a smart pointer, like boost::shared_ptr. This would solve the problems mentioned above. To understand why, read about RAII.

Community
  • 1
  • 1
Björn Pollex
  • 75,346
  • 28
  • 201
  • 283
  • 3
    `std::auto_ptr` (or its replacement in the new standard, `std::unique_ptr`) would work here too. – Fred Larson Jun 22 '11 at 19:33
  • I actually wasn't sure if I needed to dereference or not. I figured I'm not actually writing a program right now though, so it's fine for the sake of the question. You all knew what I meant anyway :) – MGZero Jun 22 '11 at 19:40
  • 2
    @MGZero: I am sorry, but this makes me a little bit angry. We spend time here to help people solve their problems. If the people that ask questions leave us guessing weather the errors in their programs are typos due to laziness, or the actual errors causing their problems, then this is **really demotivating**. Please do not do this in the future. Read [this page](http://sscce.org), twice, and think of it every time you ask a question. – Björn Pollex Jun 22 '11 at 19:43
  • 1
    Excuse me, but I think you're overreacting a little bit. Thank you for your answer. Good day. – MGZero Jun 22 '11 at 19:54
1

(Edited)

Yes, the second is fine, so long as you dereference that 'x' before assigning!

DanTheMan
  • 3,277
  • 2
  • 21
  • 40
1

You might be making int * as just an example, but really, in the case you noted, there is not a reason to return int *, just return int, the actual value is more than good enough. I see these situations all the time, getting overly complicated, when, what is actually needed, is just to simplify.

In the case of 'int *', I can only really think of a realistic case of returning an array of ints, if so, then you need to allocate that, return that, and hopefully, in your documentation, note that it has to be released.

James John McGuire 'Jahmic'
  • 11,728
  • 11
  • 67
  • 78
  • 1
    If this code is going in a shared library you'll need to provide a deallocation function yourself. The library might be compiled under different conditions from the library caller, so there would be conflicting systems of `new` and `delete`. – Chris Lutz Jun 22 '11 at 19:30
  • @Chris Lutz - Yes, quite good point, can't remember everything. – James John McGuire 'Jahmic' Jun 22 '11 at 19:55
1

The first approach certainly leads to problems, as you are now well aware.

The second is kind of OK, but demands attention from the programmer because he needs to explicitly delete the returned pointer (as you did). This is harder when your application grows larger, using this method will probably cause problems (memory leaks) as the programmer will find it difficult to keep track of every single variable he needs to deallocate.

A 3rd approach for this scenario, is to pass a variable by reference to be used inside the function, which is way safer.

void somefunc(int& value)
{
    value = 5;
}

// some code that calls somefunc()
int a_value = 0;
somefunc(a_value);
// printing a_value will display 5 
karlphillip
  • 92,053
  • 36
  • 243
  • 426
1

Yes, you're taking the risk of leaking memory. (compile errors aside.) Doing this for an int is silly, but the principle is the same even if it's a large structure.

But understand: you've written C-style code, where you have a function that allocates storage.

If you're trying to learn C++, you should put somefunc() and the data it operates on into a class. Methods and data together. A class can also do RAII as Space_C0wb0y pointed out.

Erik Olson
  • 1,154
  • 8
  • 18
  • 1
    All functions don't necessarily need to go in a class. – Chris Lutz Jun 22 '11 at 19:31
  • No, I'm not trying to learn C++, I've been using it for 6 years now. I was just wondering about a general issue that came up today. Thank you, though! – MGZero Jun 22 '11 at 20:42
0

Ok, I would analyze this by answering these questions:

  1. What does x contain ? - A memory location(since it is a pointer variable)
  2. What is the scope of x? - Since it a a auto variable it's scope is limited to the function somefunc()
  3. What happens to auto variables once they exit the local scope ? - They are deleted from the stack space.
  4. So what happens to x now after return from somefunc()? - Since it is an auto variable declared on the stack , it's scope(lifetime) is limited to somefunc() and hence will be deleted.
  5. Ok so now, what happens to the value pointed to by x? We have a memory leak as the value is allocated on the heap and we have just lost the address when x is deleted.
  6. What does y get? - No idea.
  7. What happens when y is deleted? - No idea.
Eternal Learner
  • 3,800
  • 13
  • 48
  • 78
0

The point is not to return a pointer or reference to a local variable, because once the function returns, locals don't exist.

However, the return value still exists, and dynamically allocated memory certainly exists as well.

In C++, we prefer to avoid raw pointers whenever possible. To "return a value that already exists" (i.e. the function does not create a new value), use a reference. To "return a value that didn't already exist" (i.e. the function creates a new value, in the idiomatic sense, not the new keyword sense) use a value, or if necessary, some kind of smart pointer wrapper.

Karl Knechtel
  • 62,466
  • 11
  • 102
  • 153
-2

It's both memory leak and a crash (because of the delete).

tp1
  • 288
  • 1
  • 3