简体   繁体   中英

C++, will this cause memory leak?

I know that I can't get a reference of a local var. such as:

int& func1()
{
    int i;
    i = 1;
    return i;
}

And I know that this is correct, but I have to delete it after calling func2()

int* func2()
{
    int* p;
    p = new int;


       *p = 1;
        return p;
}

int main()
{
    int *p = func2();
    cout << *p << endl;
    delete p;
    return 0;
}

If the function is like this:

MyClass MyFunction()
{
    return new MyClass;
}

MyClass's whole definition is:

class MyClass
{
public:
    MyClass() : num(1){}
    MyClass(MyClass*) : num(10){}
    int num;
};

Will this cause memory leak?

How should I avoid it? the function returns an object not a pointer, so how can I delete it?

PS: the code comes from the book "Ruminations on C++" Chapter 10. the original code is:

Picture frame(const Pictrue& pic)
{
    // Picture has a constructor Picture(*P_Node)
    // Frame_Pic derives from P_Node
    // So the constructor Picture(*P_Node) will implicitly convert Frame_Pic to Picture.
    return new Frame_Pic(pic);
}
MyClass MyFunction() 
{     
return new MyClass; 
} 

This is actually wrong.you are returning a pointer . so it should be

MyClass* MyFunction()

if your function is as i mentioned above and if you are not deleting it after using it.it will leak memory.

How should I avoid it? the function returns an object not a pointer, so how can I delete it?

that is a compilation error.so the point of deleting it will not rise

If you delete the pointer returned from the funciton there is no memory leak. However this is error prone since it means that every client of the function must know that it should delete the return value. It's much better style to use a smart pointer (either shared_ptr or unique_ptr according to semantics).

The same goes to the Picture example. If this object correctly manages its resources (ie deletes in the destructor and has a good copy constructor and operator= (in accordance with the Rule of Three ), then there is no memory leak.

With your updated MyClass that has the pointer constructor, I suppose you should write:

MyClass MyFunction() {
    MyClass *ptr = new MyClass;
    MyClass retval(ptr);
    delete ptr;   // the dynamically-allocated object isn't needed any more
    return retval;
}

That happens to be exception-safe, since the constructor of MyClass can't throw, but as a general rule you really shouldn't ever call new without putting the result straight into a smart pointer:

MyClass MyFunction() {
    std::unique_ptr<MyClass>(new MyClass);
    return MyClass(ptr);
}

It's a fairly absurd situation anyway - if you're going to return by value, there's no reason to call new at all:

MyClass MyFunction() {
    MyClass tmpvalue;
    return &tmpvalue; // doesn't actually return the pointer, just an object
                      // constructed from it
}

And since the value of the pointer isn't even used by the pointer constructor, you could just as well write:

MyClass MyFunction() {
    return 0; // returns an object constructed from a null pointer
}

In the original code your quote from the book, I guess that the class Picture has a data member of type P_Node* , in which it stores the pointer value, and calls delete on that pointer in its destructor. Hopefully the author also does something about the copy constructor and copy assignment operator of Picture , to prevent a double-free after the copy. I don't have the book, so I can't check my guess, but the code for Picture should show how it's done.

[Edit: oh, that's one of the books by Koenig and Moo. They are (more than) competent, so pretty certainly their Picture class handles the resource correctly. If it doesn't, it's because it's a deliberate example of Doing It Wrong.]

A simple check would be this:

  • If you're using N number of new in your program, then you've to use N number of compatible 1 delete in your program to avoid memory leak 2 .

So are you doing that? Yes, in the first case (in which you're doing new int ) you're doint that. There is no memory leak.

And rest of the post isn't clear enough to me!


1. By compatible delete , I mean if you're using new in the form of ptr = new T[M] , then the compatible delete should be of the form of delete []ptr . Similarly, delete ptr is compatible with ptr = new T .

2. Of course, if you're using some smart pointers, then you don't have to use delete explictly.

It's the same as your "func2" example. who ever call "frame" need to free the returning Picture in the end.

MyClass MyFunction()
{
    return new MyClass;
}

is incorrect, because operator new returns a pointer to MyClass, but your function returns MyClass, not MyClass*

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM