5

I'm asking this question to relieve myself of the confusion I've been having about the following program. I know using an array in certain contexts will make the array to decay to a single pointer to its first element. I have a function that returns this array by pointer (this function is created using new[]). Will the array decay, causing the pointer to point only to the first element? Here is an example:

int *foo() {
    int *t = new int[10];

    return t;
}

int main() {
    int *p = foo();
}

This is where the confusion follows. I don't know if p points to the first element or to the entire array. So I have the following questions:

  • Does returning the array by pointer cause the decay of it (and consequentially cause a memory leak)?
  • Does p point to the array's first element?
  • Does using delete[] on p cause undefined behavior if the above two are true?

I'm hoping these questions can be answered so I can fully understand this program. Thank you.

Me myself and I
  • 3,990
  • 1
  • 23
  • 47
  • 1
    if your next line was `p = ''` or something, you'd "lose" the pointer returned from foo, and boom... memory leak. It's only a memory leak if you neglect to clean up any memory you allocated. and part of that can be "forgeting" or "losing" pointers to that memory. – Marc B Feb 17 '13 at 23:35
  • "decay" doesn't do anything at all to the objects created with dynamic storage duration. It just describes something that happens to array expressions, treating them as pointer types. – aschepler Feb 17 '13 at 23:38
  • Memory leaks are not about how you pass pointers across your application but it's about how you make sure ("manage it") that all the memory that has been allocated is being deallocated as well. The easier the memory management is, the less is the chance that there's a memory leak in your code ~> so just follow [RAII](http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization) as much as possible :) – LihO Feb 17 '13 at 23:43
  • Decay only affects *variables* of array type. You have no such thing. – Kerrek SB Feb 17 '13 at 23:45

3 Answers3

7

Does returning the array by pointer cause the decay of it (and consequentially case a memory leak)?

You are actually returning a copy of t, which is a pointer. It already points at the first element of a dynamically allocated array. There would only be a memory leak if you failed to call delete [] on it.

Does p point to the array's first element?

Yes

Does using delete[] on p cause undefined behavior if the above two are true?

No, it is fine to do that. As long as the function is returning a pointer to a dynamically allocated array.

You have identified a serious problem with this idiom: you cannot know if you are getting a pointer to an element, a pointer to the first element of a dynamically allocated array, a pointer to a global. You cannot know by looking at the return type of the function whether you need to call delete, delete [], or not call delete at all. Solution: do not return a pointer! Return a type that beter expresses what is going on, and that takes care of managing its own resources (std::vector, std::array, std::unique_ptr, std::shared_ptr...).

David G
  • 94,763
  • 41
  • 167
  • 253
juanchopanza
  • 223,364
  • 34
  • 402
  • 480
6

Your function allocates memory and returns a pointer to it, or more technically, to the first element as you knew it correctly.

What happens with the memory afterwards is up to the caller. This means that when the array returned isn't used any longer, it should be deleted by the caller using delete[]. If the caller doesn't respect this rule, the program leaks memory. If you write code like that, you should strongly emphasize this in the documentation of your method!

The more modern solution for stuff like that is to use smart pointers. Smart pointers are by themselves objects (not pointers to ones) which guard an underlying pointer. Depending on the type of smart pointer we are talking here, it will be deleted automatically when running out of scope in the caller (which uniquely holds the ownership to the allocated memory), or when it is no longer used by others (shared ownership).

See this question for details: smart pointers and arrays

Now if the function was written like in your question, so it returns a raw pointer rather than a smart one, you can still make use of the capabilities of smart pointers within the caller by wrapping the array afterwards.

Regarding the numbers of elements / the amount of memory to be deleted, that's completely up to the implementation of delete[], so you don't have to worry about the number of elements in the caller. However, you also can't query the number of elements to work with them. If you need the number of elements, you have to return them too, maybe via an "out parameter".

In modern C++, I strongly recommend using data structures different from raw arrays, like std::vector for example, or std::map if you need an associative container, and problems such as "who deletes this allocated memory?" are gone.

Community
  • 1
  • 1
leemes
  • 44,967
  • 21
  • 135
  • 183
0

Does using delete[] on p cause undefined behavior if the above two are true?

no, not delete[] p will result in a memory leak!

However, delete[] magically knows how long the array is, sizeof(p) does not, because the allocator keeps track of the allocated space. However sizeof is a fixed value generated at compiletime

El Hocko
  • 2,581
  • 1
  • 13
  • 22