mille271
mille271

Reputation: 81

When to delete pointer in try-catch block

Quick best-practice question (note I am not allowed to use any smart pointers in this code). I am under the impression that if I pass a pointer to a function and an exceptional case occurs, then the memory is leaked if it's never deleted in either the called function or the function in which the memory was first allocated. Is it safe to delete the memory in the catch blocks or should I delete the memory in the calling function?

Example:

int main() {
  object* myPtr = new object(); //dynamic memory on heap
  foo(*myPtr);  //pass pointer to function foo

  return 0;
}

void foo(object &pointer) {
  try {
    /* do stuff here
    with the pointer */
  }
  catch (const char &e) {
    cout<< "An error occured: " << e << endl;
  }
  catch (...)
    cout<< "Caught unknown exception." << endl;
  }
}

Should I delete the pointer after the function returns?

 int main() {
      object* myPtr = new object(); //dynamic memory on heap
      foo(*myPtr);  //pass pointer to function foo
      delete myPtr;

      return 0;
    }

Or in the try-catch blocks?

void foo(object &pointer) {
      try {
        /* do stuff here
        with the pointer */
      }
      catch (const char &e) {
        cout<< "An error occured: " << e << endl;
        delete &pointer;
      }
      catch (...)
        cout<< "Caught unknown exception." << endl;
        delete &pointer;
      }
    }

Upvotes: 2

Views: 3220

Answers (2)

Remy Lebeau
Remy Lebeau

Reputation: 595349

I am under the impression that if I pass a pointer to a function and an exceptional case occurs, then the memory is leaked if it's never deleted in either the called function or the function in which the memory was first allocated.

It is not required that the memory be freed in the same function that allocated it. But yes, in general, if the pointer is pointing at memory that was allocated with new then it is leaked if delete is never called on it at all, regardless of where that is actually called.

Is it safe to delete the memory in the catch blocks or should I delete the memory in the calling function?

In your example, foo() has no concept of how the object is allocated, so no, it is not safe to call delete inside of foo().

For example, you could call foo() using one of this instead, all of which would have problems if foo() called delete:

int main() {
    object myObj;
    foo(myObj);
    return 0;
}

int main() {
    std::unique_ptr<object> myPtr(new object);
    foo(*myPtr);
    return 0;
}

int main() {
    std::vector<char> buffer(sizeof(object));
    object *myPtr = new (&buffer[0]) object;
    foo(*myPtr);
    myPtr->~object();
    return 0;
}

From foo's perspective, it doesn't matter how the object is allocated, as long as it is a valid object instance going into foo(). Since main() decides how the object is allocated, main() should be the one to decide how to free it correctly, if at all.

Upvotes: 3

Lightness Races in Orbit
Lightness Races in Orbit

Reputation: 385088

When to delete pointer in try-catch block

Don't.

Delete it in main, after the call to foo.

In short, delete it where you created it. Anything else creates a messy asymmetry.


I am under the impression that if I pass a pointer to a function and an exceptional case occurs, then the memory is leaked if it's never deleted.

Don't know where you heard that. Forget it. It's nonsense.


Is it safe to delete the memory in the catch blocks or should I delete the memory in the calling function?

You could:

  1. delete the memory at the end of the try and in both catch blocks
  2. delete the memory after the end try/catch chain

and both are perfectly "safe".

But, like I said—


Should I delete the pointer after the function returns?

Right, exactly.


BTW

You have a missing * and a capitalisation typo:

object* myPtr = new object();
//    ^             ^

and in reality a version with smart pointers might look like this:

#include <iostream>
#include <memory>

struct object {};

void foo(object& obj)
{
   try {
      // do stuff here with the reference (not a pointer)
   }
   catch (const char* e) {
      std::cout << "An error occured: " << e << std::endl;
   }
   catch (...)
      std::cout << "Caught unknown exception." << std::endl;
   }
}

int main()
{
   auto myPtr = std::make_unique<object>();
   foo(*myPtr);
}

Upvotes: 6

Related Questions