std::unique_ptr and exception safety - c++

Do I need to wrap std::unique_ptr usage with try/catch in code which should be exception safe?
std::unique_ptr will hold a raw memory block created by ::malloc (with my custom deleter to call ::free).

All of std::unique_ptr's constructors* are noexcept
malloc won't throw any exception on failure... it will just return nullptr.
I believe your deleter's constructors won't throw anything either.
So you don't need to catch anything, since nothing will be thrown.
*: See C++11 §20.7.1.2.1 unique_ptr constructors [unique.ptr.single.ctor]

As mentioned in the comments, this answer is relevant for C++14 only.
Despite the good answer from #keenyt, it's worth to say that std::make_unique<T> can throw, even though the constructors of std::unique_ptr are noexcept.
Actually, whether the above mentioned statement throws or not mostly depends on the constructors of the type T involved.
As an example from cppreference.com for std::make_unique:
May throw std::bad_alloc or any exception thrown by the constructor of T. If an exception is thrown, this function has no effect.
So, a refinement of the answer would be: no, you don't need a try/catch block, unless you are using std::make_unique and the constructors of your type T can throw.

Related

Is it possible that make_shared has no any exception but returns a nullptr?

I am recently dealing with a problem with shared_ptr. I am curious if make_shared failed, it will raise exceptions right? Is there any kind of situation that the make_shared returned a nullptr but without any exceptions?
From the docs:
std::make_shared
...
May throw std::bad_alloc or any exception thrown by the constructor of
T.
So, if you throw exception from your class' constructor, then std::make_shared will throw it too. Besides exceptions thrown from constructor, std::make_shared could throw std::bad_alloc exception on its own.
Therefore, you don't need to check if the result of std::make_shared is nullptr. Just be sure to catch the exception and properly handle it.

Should C++ allocator::allocate throw or not?

The Allocator concept and std::allocator_traits doesn't say whether allocate will throw or not.
So when I'm writing a container using allocators, how to know whether to check return type or use catch?
The table in the Requirements section of the page you reference gives quite enough information when it may throw exceptions and when it must not throw exceptions. Below is a quote when an allocator may throw exceptions.
a.allocate(n) allocates storage suitable for n objects of type T, but does not construct them. May throw exceptions.
What type of exceptions is thrown is not described there and maybe is implementation dependent. Generally it is std::bad_alloc in STL.
Yes, it may throw. And the exception is std::bad_alloc since it use the allocator passed to it while std::allocator will throw std::bad_alloc.
In the page you refered introduces two scenarios:
Calls a.allocate(n)
Additionally passes memory locality hint hint. Calls a.allocate(n, hint) if possible. If not possible (e.g. a has no two-argument member function allocate()), calls a.allocate(n)
so basically you can turn to this:
http://en.cppreference.com/w/cpp/memory/allocator/allocate

Is this a safe way of throwing an exception from a destructor?

I know that throwing from a destructor is in general a bad idea, but I was wondering if i could use std::uncaught_exception() to safely throw from a destructor.
Consider the following RAII type:
struct RAIIType {
...
~RAIIType() {
//do stuff..
if (SomethingBadHappened()) {
//Assume that if an exception is already active, we don't really need to detect this error
if (!std::uncaught_exception()) {
throw std::runtime_error("Data corrupted");
}
}
}
};
Is this UB in c++11? Is it a bad design?
You have an if, did you think about the "other" condition? It can throw an exception or... do what? There's two things that can be in the other branch.
Nothing (If nothing needs to happen when the error occurs, why throw an exception?)
It "handles" the exception (If it can be "handled", why throw an exception?)
Now that we've established that there's no purpose to throwing an exception conditionally like that, the rest of the question is sort of moot. But here's a tidbit: NEVER THROW EXCEPTIONS FROM DESTRUCTORS. If an object throws an exception, the calling code normally checks that object in some way to "handle" the exception. If that object no longer exists, there's usually no way to "handle" the exception, meaning the exception should not be thrown. Either it's ignored, or the program makes a dump file and aborts. So throwing exceptions from destructors is pointless anyway, because catching it is pointless. With this is mind, classes assume that destructors won't throw, and virtually every class leaks resources if a destructor throws. So NEVER THROW EXCEPTIONS FROM DESTRUCTORS.
Note that your code doesn't do what you think it does. In case SomethingBadHappened and there is no stack unwinding in place, you attempt to throw from a destructor and nonetheless std::terminate is called. This is the new behavior in C++11 (see this article). You will need to annotate your destructor with noexcept(false) specification.
Suppose you do this, it is not clear what you mean by "safely". Your destructor never triggers std::terminate directly. But calling std::terminate is not a UB: it is very well defined and useful (see this article).
For sure, you cannot put your class RAIIType into STL containers. The C++ Standard explicitly calls that UB (when a destructor throws in an STL container).
Also, the design look suspicious: the if-statement really means "sometimes report a failure and sometimes not". Are you fine with this?
See also this post for a similar discussion.
I know that throwing from a destructor is in general a bad idea, but I was wondering if i could use std::uncaught_exception() to safely throw from a destructor.
You may like to have a look at uncaught_exceptions proposal from Herb Sutter:
Motivation
std::uncaught_exception is known to be “nearly useful” in many situations, such as when implementing an Alexandrescu-style ScopeGuard. [1]
In particular, when called in a destructor, what C++ programmers often expect and what is basically true is: “uncaught_exception returns true iff this destructor is being called during stack unwinding.”
However, as documented at least since 1998 in Guru of the Week #47, it means code that is transitively called from a destructor that could itself be invoked during stack unwinding cannot correctly detect whether it itself is actually being called as part of unwinding. Once you’re in unwinding of any exception, to uncaught_exception everything looks like unwinding, even if there is more than
one active exception.
...
This paper proposes a new function int std::uncaught_exceptions() that returns the number of exceptions currently active, meaning thrown or rethrown but not yet handled.
A type that wants to know whether its destructor is being run to unwind this object can query uncaught_exceptions in its constructor and store the result, then query uncaught_exceptions again in its destructor; if the result is different, then this destructor is being invoked as part of stack unwinding
due to a new exception that was thrown later than the object’s construction.
It depends what you mean by "safely".
That will prevent one of the issues with throwing from a destructor - the program won't be terminated if the error happens during stack unwinding when handling another exception.
However, there are still issues, among them:
If you have an array of these, then they may not all be destroyed if one throws on destruction.
Some exception-safety idioms rely on non-throwing destruction.
Many people (such as myself) don't know all the rules governing what will or won't be correctly destroyed if a destructor throws, and won't be confident that they can use your class safely.

How can shared_ptr offer noexcept assignment?

How can std::shared_ptr offer a noexcept operator=? Surely, if this shared_ptr is the last one, then it will have to destroy its contents, and it can't guarantee that the destructor of that object does not throw, or the custom deleter used originally does not throw.
Looks like a defect to me, though not one I can find in the active issues list (though #2104 is similar).
Per [C++11: 20.7.2.2.3/1], the assignment is defined to be equivalent to shared_ptr(r).swap(*this);
But per [C++11: 20.7.2.2.2], ~shared_ptr itself is not noexcept.
Unless I've misunderstood the way in which noexcept works, this must be an error.
Alternatively it could simply mean that the assignment operator is only usable when neither the underlying object type nor the deleter type throw on destruction, though even in such a scenario, the lack of any informative note in the standard wording makes me think that this is unlikely.
According to the isocpp forums, shared_ptr simply assumes that the deleter will not throw, and otherwise is UB. This would mean that the real defect is that shared_ptr's destructor is not marked as nothrow.
It's important to note that reset() (without parameters) and swap are declared nothrow as well.
Also if we take a look at boost::shared_ptr it provides the same declarations, except it also declares it's destructor as never throws which std::shared_ptr for some reason doesn't.
As far as I understand, what it means is not "I guarantee that ~T() will not throw", but "I prohibit ~T() to throw and hope you know what you are doing".

Are C++ Containers exception-safe?

I use the implicit Constructor and a load() Member which inputs the Attributes, but can also throw exceptions.
My question is: if the Attributes are everyday C++ Containers will I get memory leaks if exceptions happen in load()?
Thank you for reading.
Edit: example code to help clarify my question.
class One
{
public:
std::vector<int> stuff;
void load() {
stuff.resize(13);
stuff[0] = 43;
std::bad_alloc ba;
throw ba; // will this cause memory leaks? (as far as this class is concerned)
}
}
I know this is a silly question but I had to ask it.
The container itself is exception safe.
But it also depends on the type being placed in the contain and if it has been written correctly.
i.e.: Exceptions should not escape the destructor
The standard defines the following guarantees on containers and exceptions:
23.2.1 General container requirements [container.requirements.general]
Paragraph 10:
Unless otherwise specified (see 23.2.4.1, 23.2.5.1, 23.3.3.4, and 23.3.6.5) all container types defined in this Clause meet the following additional requirements:
— if an exception is thrown by an insert() function while inserting a single element, that function has no effects.
— if an exception is thrown by a push_back() or push_front() function, that function has no effects.
— no erase(), clear(), pop_back() or pop_front() function throws an exception.
— no copy constructor or assignment operator of a returned iterator throws an exception.
— no swap() function throws an exception.
Yes, containers are exception safe. As long as you aren't doing shenanigans like allocating them on the heap (without exception-safe smart pointers) or such like that, you'll be fine.
Since your question doesn't state much, here is my take.
If you are allocating memory using new/new[] (inside your load()) then you have to deallocate using delete/delete[], when exception is thrown.
If you are allocating as an automatic variable then they are exception safe.