Reputation: 146
I want to use Hinnant's stack allocator (documentation, implementation) in combination with STL containers but I want to modify it such that dynamic memory allocation NEVER takes place.
One thing that must be done to fulfil this is to replace the new/delete calls in the allocate/deallocate methods that take place if there is no room on the stack supplied buffer.
But how should I deal with exceptions? The STL containers may throw exceptions, e.g.
std::vector::at
"The function automatically checks whether n is within the bounds of valid elements in the vector, throwing an out_of_range exception if it is not [...]"
http://www.cplusplus.com/reference/vector/vector/at/
I could not find a clear answer whether exceptions are stored in dynamic or static memory. Only these lines give hints:
From [except.throw]/15.1/4:
The memory for the exception object is allocated in an unspecified way, except as noted in 3.7.4.1.
The final reference, [basic.stc.dynamic.allocation]/4, says:
[Note: In particular, a global allocation function is not called to allocate storage for [...] an exception object (15.1). — end note]
https://stackoverflow.com/a/27259902/8007684
What exactly does this mean? Is the memory reserved for exceptions placed in static memory? Or are there still any allocations happening in an "unspecified way" which would mean exceptions would be stored dynamically? The quoted description leads much space for interpretation...
So my basic question is: Is it safe to use STL containers+Hinnant's stack allocator if dynamic memory usage is forbidden? Or does this not work and I either have to use -fno-exceptions
to replace exceptions by abort()
calls or implement my own replacements of STL containers that do not throw exceptions...?
Thanks in advance!
inspire
Upvotes: 6
Views: 366
Reputation: 219335
The gcc and clang implementations follow a specification called the Itanium ABI. It says, among other things:
Storage is needed for exceptions being thrown. This storage must persist while stack is being unwound, since it will be used by the handler, and must be thread-safe. Exception object storage will therefore normally be allocated in the heap, although implementations may provide an emergency buffer to support throwing
bad_alloc
exceptions under low memory conditions (see Section 3.3.1).Memory will be allocated by the
__cxa_allocate_exception
runtime library routine. This routine is passed the size of the exception object to be thrown (not including the size of the__cxa_exception
header), and returns a pointer to the temporary space for the exception object. It will allocate the exception memory on the heap if possible. If heap allocation fails, an implementation may use other backup mechanisms (see Section 3.4.1).If
__cxa_allocate_exception
cannot allocate an exception object under these constraints, it callsterminate()
.
The libc++abi implementation of __cxa_allocate_exception
is here. It will first go to the heap, and if that fails, try an emergency backup buffer that is statically allocated within the libc++abi.dylib. If both the heap, and the emergency-stash fail to allocate enough memory for the arbitrary-sized user-created exception, terminate()
is called.
Upvotes: 5