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
Related
Exception for the member function at(), I cannot think of exceptions being thrown by std::vector functions but by its allocator or by its elements constructors and assignment operators. Therefore, exception neutrality can be a very desirable guarantee when implementing your own allocators. For example, you might allocate all required memory up-front and then rely on the noexcept guarantee of an allocator to propagate to its container.
Does the C++ standard provide exception neutrality of std::vector<T,Alloc>?
Besides memory allocations, there is one situation where vector itself will also throw exceptions: the at() member function.
So, after reserve()ing sufficient memory, you are guaranteed that no exceptions will be thrown, provided that the vector's class's constructors and assignment operators (which will be called as part of modifying the vector) do not throw any exceptions either, and there are no out of range calls to at().
Consider some standard container which uses dynamic memory (i.e. is an AllocatorAwareContainer) and has a size and capacity of zero. For example, take a std::vector and call vec.resize(0); vec.shrink_to_fit();.
I would imagine that such container instances would contain only nullptr pointers for their logical contents and std::size_t members to track information like size. I would also imagine that their destructors would do essentially nothing, as there is no dynamic memory to be freed.
All destructors of containers, as I know, are noexcept. I.e. on throwing of an exception during destruction they should call std::terminate. It is possible in case of Allocator::deallocate() throw exception.
Can I be sure containers in the state, described above, never call std::terminate on destruction?
It is possible in case of Allocator::deallocate() throw exception.
No, it's not. The requirements for Allocator forbid deallocate to throw. It's not a formal noexcept specifier, but C++14 Table 28 Allocator requirements says:
a.deallocate(p, n) [...] Does not throw exceptions.
So if your allocator throws on deallocation, that's a violation of the required contract and all bets are off anyway.
For STL containers (so far, std::vector<> and std::deque<>), I'm looking for documentation that says exactly when they throw exceptions. Something like, "It throws X in situation A. It throws Y in situation B. It throws no other exceptions under any circumstances."
I'd like to reassure my exception-phobic colleagues that we know exactly what can trigger exceptions in the STL classes we use.
The most accurate information will come from the C++ standard matching your compiler, and compiler documentation. However, the spec costs money. If you're willing to settle for a few typos, the draft C++11 specification can be found here: http://open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf for free, and the latest publicly available draft (preparing for C++14) seems to be http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3797.pdf.
The number 1 used container is vector, so lets go over that.
Technically the only vector member that throws an exception is at, if given an out of range index. (tada! we're done!)
Less technically, vector assign/insert/emplace/reserve/resize/push_back/emplace_back/shrink_to_fit/etc can cause a resize, which uses std::allocator<T>:allocate, which can throw std::bad_alloc in theory. In weird situations with weird allocators, swap can also trigger this too. On some systems (Linux), this pretty much never happens, because it only throws if it runs out of virtual memory, and often the program will run out of physical memory first, and the OS will simply kill the whole program. That happens regardless of exceptions though, so this doesn't count against C++ exceptions.
Probably relevant is that the elements in a vector can throw any exception when copied, which affects constructors, assignment, insert/emplace/push_back/emplace_back, reserve, resize/shrink_to_fit. (If your element has a noexcept move constructor and move assignment, and it really really really should, then happens only when copying the entire vector).
The spec details exactly what exceptions are thrown and often also specifies under exactly what conditions they're thrown.
The C++ standard documents when exceptions will be thrown and under what circumstances for the standard library containers. There are also general rules about which methods will not throw exceptions for containers.
Alternatively, you can search the headers for throw (or the equivalent macro) to determine under what circumstances exceptions will trigger.
I am C# programmer but now I want to get more into C++.
I know the basics of C++ but I don't know how to handle errors.
For example: I am writing a library. I create an constructor which requests an integer as an argument.
If that integer is bigger than 50, it is an error.
In C# I would throw an ArgumentOutOfRange exception, but what should I do in C++?
In C# I would throw an ArgumentOutOfRange exception but what should I do in c++?
First you should consider if that should not be a precondition of your function, leaving the responsibility of checking whether the value is in range to the caller.
If you decide for this option, then invoking the function with an out-of-range value would be undefined behavior, and inside the function you could just have a debug assertion to help you spot possible misuses - without the need of throwing any exception.
If you decide that the function should have a wide contract, on the other hand, and react in a well-defined way by throwing an exception when the argument is outside the permitted range, then you could throw an std::out_of_range exception.
For example: I am writing a libary [...]
If you are writing a library, meaning that you do not know the exact requirements of your clients in terms of performance and robustness, you may consider providing two such functions - one with a wide contract that throws exceptions, and one with a narrow contract that assumes the client provides meaningful input.
This way, the user of your library could decide based on their use cases whether or not it is OK to pay for the overhead of checking the correctness of the input each time your function is called.
This is, for instance, the strategy adopted by the C++ Standard Library for std::vector, which provides a non-throwing operator[] with a narrow contract for accessing elements of the collection based on the index (this function has undefined behavior if the index is out-of-bounds), and a member function at() that performs index checking and throws an exception if the index is out-of-bounds.
It depends on whether an integer larger than 50 could possibly be passed to the constructor as part of normal program flow, or whether that's an exceptional condition. But in general the only way to have object construction fail is by throwing an exception.
Your user code might look like this:
int n = parse_user_input()
if (n < 50)
{
Foo x(n);
x.do_cool_stuff();
}
else
{
// report user error
}
That is, you don't actually use exceptions for normal control flow. With that sort of code pattern, it would be perfectly fine for Foo::Foo(int) to throw an exception if the argument were out of range.
You can find useful standard exception classes in <stdexcept>.
The same thing as in C#: throw an exception. This is the only way to prevent an object from being constructed.
std::invalid_argument is a good standard choice regarding what to throw.
From the C++ FAQ: [17.8] How can I handle a constructor that fails?
Excerpt:
Throw an exception.
Constructors don't have a return type, so it's not possible to use
return codes. The best way to signal constructor failure is therefore
to throw an exception. If you don't have the option of using
exceptions, the "least bad" work-around is to put the object into a
"zombie" state by setting an internal status bit so the object acts
sort of like it's dead even though it is technically still alive.
So, throwing std::invalid_argument or std::out_of_range would be perfectly acceptable for your situation. You could also throw a custom exception if that would be beneficial in your situation. In the C++ FAQ see: [17.12] What should I throw?
Destructors may not throw exceptions (so stack unwinding can complete during exception handling), and must deallocate any resources allocated to the object (so no resources leak). A design for an object that contains several other objects (or is allocated several resources) might record pointers to them in an STL container. The destructor would therefore use the following iterator-related methods:
begin(), end() for the container
operator++ for a valid iterator
operator* or operator-> for a valid iterator
But to guarantee that the destructor both does not throw exceptions and deallocates its resources you would need to rely on those methods never throwing exceptions.
Is it safe to rely on those methods never throwing exceptions? It is hard to imagine a practical implementation that would throw exceptions, as under the hood an STL iterator is essentially a pointer. But does standard C++ require that those methods never throw exceptions? I've not found a clear statement in the C++ standard.
Edit: The interesting case is for C++ 03 when you want to have a container of pointers to resources. There are good reasons for doing this; for example, if you have polymorphic resources. As Björn Pollex points out in his answer, if you use a container of resources (such as a std::list< Resource >) rather than a container of pointers to resources, the destructor of the container will take care of destruction (deallocation) of the Resource objects for you.
operator++ for a valid iterator
The C++ standard (I refer to N3290 draft) does not give nothrow guarantee for increment operator of iterators.
For example, std::istreambuf_iterator::operator++ effects in call to std::basic_streambuf::sbumpc. The sbumpc may call uflow which in turn may throw exception.
no copy constructor or assignment operator of a returned iterator throws an exception
That's from the C++03 standard. I don't think that the standard goes any further than that.
Btw. it's 23.1.10
The destructor would therefore use the following iterator-related
methods
No it would not. The destructor of that object would just call the destructor of the container, which would in turn be guaranteed to not throw an exception.
If you use RAII correctly, you will almost never run into a scenario where you have to explicitly release resources. This could be achieved by have the container store shared_ptr or unique_ptr, or by using something like Boost.Pointer Container.
According to http://www.tenouk.com/Module31.html these operations (for '*' and '->' it depends also on the type stored) are no throw for STL containers.