stella
stella

Reputation: 2596

What happen if exception's thrown during allocation?

I have the following function template:

template<typename T>
void init(std::vector<T>& v, int min, int max)
{
    for(int i = min; i <= max; i++)
        v.push_back(new T());
}

which will use from another function as follows:

void foo()
{
    std::vector v;
    init(v, 10, 20);
    //something else
}

what happens if some exception is thrown during initialization of some object of type T in the function init?

Do I get memory leak in that case or some other kind of UB? If so, how can I prevent it?

Upvotes: 0

Views: 179

Answers (4)

Adrian McCarthy
Adrian McCarthy

Reputation: 47954

The expression new T() typically does two things:

  1. Allocate memory for a T
  2. Construct the T in that memory

If the constructor throws an exception (and something up the stack is handling exceptions), then the memory that was allocated in step 1 will be freed before the exception is propagated up the stack. No memory leak here.

Answering what happens at the next level up requires having the code in the question clarified, because the type of the vector doesn't match its usage.

Upvotes: 1

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726479

Do I get memory leak in that case or some other kind of UB?

Assuming that T is well-behaved*, you will not get a memory leak, and behavior is fully defined.

C++ standard guarantees that it will run the destructor of std::vector<T>, cleaning up the memory that has been allocated to that vector. Moreover, C++ standard guarantees that if an exception is thrown by a push_back(), the function has no effects, meaning that your vector remains safe to destroy.

* By well-behaved I mean that T should deallocate resources associated with it. A common example of T that is not well-behaved is a plain pointer: it wouldn't take care of cleaning up.

Upvotes: 4

Steephen
Steephen

Reputation: 15824

If memory allocation fail, you will get std::bad_alloc exception. If there is exception during execution of construction of type T, that should be handled in constructor of type T using try catch block.

If std::vector::push_back failed after creation of object using new operator, there is a possibility of memory leak since newly generated raw pointer is not yet part of the vector.Since you are creating a vector of raw pointers generated using new operator, and you should call delete over the contents of vector as part of proper clean up. std::vector<> destructor only cleans up the pointers but not objects of type T.

To resolve this raw pointer issue, you can depend on std::shared_ptr or std::unique_ptr in place of raw pointer if you have C++11 compiler

Upvotes: 4

Aracthor
Aracthor

Reputation: 5907

If an exception is thrown, it will recover your functions calls until it reach a try catch block.

If there is no try catch between this call and your main, your program will exit with an error value.

You can manage it like that:

std::vector v;

try
  {
    init(v, 10, 20);
    // Init was successful, continue execution here
  }
catch (const std::exception& exception)
  {
    // An exception was thrown in init or after
    std::cerr << exception.what() << std::endl; // Print exception error message
  }

Anyway, your vector won't be affected by any memory leak if you declare it before your try-catch block.

Upvotes: 0

Related Questions