On 8/14/19 1:39 PM, Alf P. Steinbach wrote:
> On 14.08.2019 14:41, James Kuyper wrote:
>> On 8/14/19 4:25 AM, Alf P. Steinbach wrote:
>>> On 14.08.2019 10:06, Jivanmukta wrote:
...
>>>> Do you mean that in the line:
>>>>
>>>> throw exception();
>>>>
>>>> I create automatic object of a class exception?
>>>
>>> You're creating a temporary, that's copied/moved somewhere.
>>>
>>> Throwing is anyway a high cost operation. Whether it involves dynamic
>>> allocation internally depends on the C++ implementation.
>>
>> True, but only in the same sense that it is equally true of passing an
>> argument to a function
...
> From C++11 you can get what's functionally a shared pointer to an
> exception object, via `std::current_exception`.
>
> Whatever it refers to must necessarily be dynamically allocated, and an
> implementation might, for simplicity, do that up front at the throw
> point, rather than deferring the dynamic allocation in the hope that it
> will not be needed and that copying the object will be cheaper.
>
>
> [snip]
>> Any method that user code could use to detect the fact that
>> it's dynamically allocated (for instance, by trying to deallocate it)
>> has behavior not defined by the standard.
>
> There's no need to detect. With `current_exception` one knows it's
> dynamically allocated. Deallocation is a matter of destroying all owning
> smart pointers to that exception object. Which does not guarantee to
> deallocate immediately, but ensures that proper cleanup is done.
It's true that
"The referenced object shall remain valid at least as long as there is
an exception_ptr object that refers to it." (21.8.6p8).
Depending upon where it's stored, the lifetime of the exception_ptr
returned by current_exception() might be a lot longer than than the end
of the block for that exception's handler. Therefore, the referenced
object cannot, in general, be an object with automatic storage duration
local to that block. However, other parts of that same clause say:
"Returns: An exception_ptr object that refers to ... or a copy of the
currently handled exception ... It is unspecified whether the return
values of two successive calls to current_exception refer to the same
exception object. [ Note: That is, it is unspecified whether
current_exception creates a new copy each time it is called. — end note
] If the attempt to copy the current exception object throws an
exception, the function returns an exception_ptr object that refers to
the thrown exception or, if this is not possible, to an instance of
bad_exception. [ Note: The copy constructor of the thrown exception may
also fail, so the implementation is allowed to substitute a
bad_exception object to avoid infinite recursion."
Are those the semantics of a shared pointer to the current exception? As
I understand the concept, a shared pointer to something actually points
at that thing, rather than at a copy of that thing.
Given that the referenced object can be a copy of the currently handled
exception, rather than the exception itself, the lifetime of the
referenced object doesn't impose any requirements on how the exception
itself is handled. It's entirely feasible for dynamic allocation to only
occur when needed to store that copy.
>> "The name declared in an exception-declaration is local to the
>> handler..." (6.3.3p4 "Block Scope").
>> "Block-scope variables not explicitly declared static, thread_local, or
>> extern have automatic storage duration. ..." (6.7.3p1).
>> Exception declarations are not allowed to have storage class specifiers
>> (18p1), so none of those exceptions apply.
>
> Yes, but it seems that here you went out on a tangent, into the land of
> irrelevancies.
Those clauses demonstrate that the exception itself must have automatic
storage duration; a fact very relevant to the point I was making.
Allocating it dynamically is only allowed insofar as covered by the
as-if rule (the same is true of function parameters, for similar reasons).