开发者

Automatic heap cleanup during stack destruction

int* f()
{
    int *p = new int[10];
    return p;
}

int main()
{
    int *p = f();
    //using p;
    return 0;
}

Is it true that during stack destruction when function return it's value some compilers (common ones like VS or gcc were implied when I was told that) could try to automatically free memory pointed by local pointers such as p in this example? Even if it's not, would I be able to normally delete[] allocated memory in main? The problem seems to be that information about exact array size is lost at that point. Also, would the answer change in case of malloc and free?

Thank 开发者_JAVA技巧you.


Only Local variables are destroyed-released.

In your case p is "destroyed" (released) , but what what p points to, is not "destroyed" (released using delete[]).

Yes you can, and should/must use a delete[] on your main. But this does not imply using raw pointers in C++. You might find this e-book interesting : Link-Alf-Book

If you want to delete what a local variable points to when the function is "over" (out of scope) use std::auto_ptr() (only works for non-array variables though, not the ones which require delete[])

Also, would the answer change in case of malloc and free?

Nope, but you should make sure that you do not mix free()/new/delete/malloc(). The same applies for new/delete[] and new[]/delete.


No, they won't free or delete what your pointer points to. They will only release the few bytes that the pointer itself occupies. A compiler that called free or delete would, I believe, violate the language standard.

You will only be able to delete[] memory in main if you a pointer to the memory, i.e., the result from f(). You don't need keep track of the size of the allocation; new and malloc do that for you, behind the scenes.

If you want memory cleaned up at function return, use a smart pointer such as boost::scoped_ptr or boost::scoped_array (both from the Boost collection of libraries), std::auto_ptr (in the current C++ standard, but about to be deprecated) or std::unique_ptr (in the upcoming standard).

In C, it's impossible to create a smart pointer.


Is it true that during stack destruction when function return it's value some compilers (common ones like VS or gcc were implied when I was told that) could try to automatically free memory pointed by local pointers such as p in this example?

Short Answer: No

Long Answer:

If you are using smart pointers or container (like you should be) then yes.
When the smart pointer goes out of scope the memory is released.

std::auto_ptr<int> f()
{
    int *p = new int;
    return p; // smart pointer credated here and returned.
              // p should probably have been a smart pointer to start with
              // But feeling lazy this morning.
}

std::vector<int> f1()
{
    // If you want to allocate an array use a std::vector (or std::array from C++0x)
    return std::vector<int>(10);
}

int main()
{
    std::auto_ptr<int> p = f();
    std::vector<int>   p1 = f1();

    //using p;
    return 0;  // p destroyed
}

Even if it's not, would I be able to normally delete[] allocated memory in main?

It is normal to make sure all memory is correctly freed as soon as you don't need it.
Note delete [] and delete are different so be careful about using them.

Memory allocated with new must be released with delete.
Memory allocated with new [] must be released with delete [].
Memory allocated with malloc/calloc/realloc must be released with free.

The problem seems to be that information about exact array size is lost at that point.

It is the runtime systems problem to remember this information. How it is stored it is not specified by the standard but usually it is close to the object that was allocated.

Also, would the answer change in case of malloc and free?

In C++ you should probably not use malloc/free. But they can be used. When they are used you should use them together to make sure that memory is not leaked.


You were misinformed - local variables are cleaned up, but the memory allocated to local pointers is not. If you weren't returning the pointer, you would have an immediate memory leak.

Don't worry about how the compiler keeps track of how many elements were allocated, it's an implementation detail that isn't addressed by the C++ standard. Just know that it works. (As long as you use the delete[] notation, which you did)


When you use new[] the compiler adds extra bookkeeping information so that it knows how many elements to delete[]. (In a similar way, when you use malloc it knows how many bytes to free. Some compiler libraries provide extensions to find out what that size is.)


I haven't heard of a compiler doing that, but it's certainly possible for a compiler to detect (in many cases) whether the allocated memory from the function isn't referenced by a pointer anymore, and then free that memory.

In your case however, the memory is not lost because you keep a pointer to it which is the return value of the function.

A very common case for memory leaks and a perfect candidate for such a feature would be this code:

int *f()
{
    int *p = new int[10];
    // do something that doesn't pass p to external
    // functions or assign p to global data
    return p;
}

int main()
{
    while (1) {
      f();
    }
    return 0;
}

As you can notice, the pointer to the allocated memory is lost and that can be detected by the compiler with absolute certainty.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜