From: Goran on
On Apr 30, 1:04 pm, Scott Meyers <NeverR...(a)aristeia.com> wrote:
> I've asked a lot of questions about C++0x recently, so let me emphasize that I'm asking about current C++ (C++03) here.
>
> Consider:
>
> Widget *pwa = new Widget[100];
> ...
> delete [] pwa;
>
> Suppose that the destructor for pwa[50] throws. What happens next? 15.1
> tells me that "control is transferred to the nearest handler with a
> matching type," but 5.3.5/6 tells me that in a delete expression for an
> array, "the elements will be destroyed in order of decreasing address (that
> is, in reverse order of the completion of their constructor." So are
> destructors invoked for array elements 0-49?
>
> My sense is that when pwa[50]'s destructor throws, the delete expression is
> essentially abandoned (much as a looping expression would be abandoned if
> an exception occurred during iteration), elements 0-49 of the array are not
> destroyed, and the memory occupied by the array is not reclaimed by
> operator delete (because that would have been performed by the
> now-abandoned part of the delete expression), but I'd like to have more to
> go on than how I sense things. So is the behavior of the above spelled out
> by the standard?

"Doctor, it hurts when I poke myself in the eye!" much?

I don't know if it's spelled out in the standard, but I would be
HUGELY surprised if any compiler's generated code would continue to
call dtors etc after an exception was thrown. That would essentially
mean that operator delete[] is (warning: compiled with head-compiler
and tried with head-debugger):

template<typename TYPE>
void OperatorArrayDelete(TYPE* pBegin)
{
TYPE* pEnd = pBegin+ElementCount(pBegin);
while (pEnd!= pBegin)
try { (*--pEnd)->~Type(); } catch(...) {}
// Well, that catch(...) {} smells to high heaven!
SomehowFreeHeap(pBegin);
}

15.1.must take precedence over 5.3.5/6. It must!!! Aaaaaarghhhhh! :-)

Goran.


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Nick Hounsome on
On 30 Apr, 12:04, Scott Meyers <NeverR...(a)aristeia.com> wrote:
> I've asked a lot of questions about C++0x recently, so let me emphasize that I'm asking about current C++ (C++03) here.
>
> Consider:
>
> Widget *pwa = new Widget[100];
> ...
> delete [] pwa;
>
> Suppose that the destructor for pwa[50] throws. What happens next? 15.1
> tells me that "control is transferred to the nearest handler with a
> matching type," but 5.3.5/6 tells me that in a delete expression for an
> array, "the elements will be destroyed in order of decreasing address (that
> is, in reverse order of the completion of their constructor." So are
> destructors invoked for array elements 0-49?
>
> My sense is that when pwa[50]'s destructor throws, the delete expression is
> essentially abandoned (much as a looping expression would be abandoned if
> an exception occurred during iteration), elements 0-49 of the array are not
> destroyed, and the memory occupied by the array is not reclaimed by
> operator delete (because that would have been performed by the
> now-abandoned part of the delete expression), but I'd like to have more to
> go on than how I sense things. So is the behavior of the above spelled out
> by the standard?
>
> Secondarily, is the behavior specified by C++0x any different?
>
> Thanks,
>
> Scott

I don't remember what it says in the standard but I did once read a
good description of why an implementation can never "do the the right
thing" in general which boils down to the question "What would you do
if 2 (or more) of the dtors threw? (elements 3 and 6 say)"
There is no way an implementation could throw/handle exceptions for
both so an implementation would either have to silently catch and
ignore all but the first (or last) exception or stop prematurely as
you suggest and the latter is clearly the least evil.

In view of the impossibility of getting anything right in the presence
of throwing dtors (It is well known that you can't gaurantee the post
conditions of many STL methods and hence the std provides specific
restrictive wording) It seems to me that the std ought to ban
exceptions from dtors everywhere explicitly - or at least call
std::unexpected/std::terminate but as far as I can see in N3000 it's
the same old stuff (including the bit about destruction in reverse
order)

A quick google shows that according to http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#219
it's still an open issue for C++0x which confuses me because I thought
that it was supoosed to be all done and dusted apart from dotting i's
and crossing t's.


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: cpp4ever on
On 04/30/2010 02:32 PM, Goran wrote:
> On Apr 30, 1:04 pm, Scott Meyers <NeverR...(a)aristeia.com> wrote:
>> I've asked a lot of questions about C++0x recently, so let me emphasize that I'm asking about current C++ (C++03) here.
>>
>> Consider:
>>
>> Widget *pwa = new Widget[100];
>> ...
>> delete [] pwa;
>>
>> Suppose that the destructor for pwa[50] throws. What happens next? 15.1
>> tells me that "control is transferred to the nearest handler with a
>> matching type," but 5.3.5/6 tells me that in a delete expression for an
>> array, "the elements will be destroyed in order of decreasing address (that
>> is, in reverse order of the completion of their constructor." So are
>> destructors invoked for array elements 0-49?
>>
>> My sense is that when pwa[50]'s destructor throws, the delete expression is
>> essentially abandoned (much as a looping expression would be abandoned if
>> an exception occurred during iteration), elements 0-49 of the array are not
>> destroyed, and the memory occupied by the array is not reclaimed by
>> operator delete (because that would have been performed by the
>> now-abandoned part of the delete expression), but I'd like to have more to
>> go on than how I sense things. So is the behavior of the above spelled out
>> by the standard?
>
> "Doctor, it hurts when I poke myself in the eye!" much?
>
> I don't know if it's spelled out in the standard, but I would be
> HUGELY surprised if any compiler's generated code would continue to
> call dtors etc after an exception was thrown. That would essentially
> mean that operator delete[] is (warning: compiled with head-compiler
> and tried with head-debugger):
>
> template<typename TYPE>
> void OperatorArrayDelete(TYPE* pBegin)
> {
> TYPE* pEnd = pBegin+ElementCount(pBegin);
> while (pEnd!= pBegin)
> try { (*--pEnd)->~Type(); } catch(...) {}
> // Well, that catch(...) {} smells to high heaven!
> SomehowFreeHeap(pBegin);
> }
>
> 15.1.must take precedence over 5.3.5/6. It must!!! Aaaaaarghhhhh! :-)
>
> Goran.
>
>
Goran has a damn fine point, depends where the exception is caught, and
what it then does. IMHO if you get an unexpected exception in a
destructor then something is potentially broken, and badly! Personally I
often spend more time on constructors and destructors than most other
member functions to avoid exceptions there. Getting it right is easier
than debugging, especially in those situations.

Regards

JB

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Goran on
On Apr 30, 7:19 pm, cpp4ever <n2xssvv.g02gfr12...(a)ntlworld.com> wrote:
> On 04/30/2010 02:32 PM, Goran wrote:
>
>> On Apr 30, 1:04 pm, Scott Meyers <NeverR...(a)aristeia.com> wrote:
>>> I've asked a lot of questions about C++0x recently, so let me emphasize that I'm asking about current C++ (C++03) here.
>
>>> Consider:
>
>>> Widget *pwa = new Widget[100];
>>> ...
>>> delete [] pwa;
>
>>> Suppose that the destructor for pwa[50] throws. What happens next? 15.1
>>> tells me that "control is transferred to the nearest handler with a
>>> matching type," but 5.3.5/6 tells me that in a delete expression for an
>>> array, "the elements will be destroyed in order of decreasing address (that
>>> is, in reverse order of the completion of their constructor." So are
>>> destructors invoked for array elements 0-49?
>
>>> My sense is that when pwa[50]'s destructor throws, the delete expression is
>>> essentially abandoned (much as a looping expression would be abandoned if
>>> an exception occurred during iteration), elements 0-49 of the array are not
>>> destroyed, and the memory occupied by the array is not reclaimed by
>>> operator delete (because that would have been performed by the
>>> now-abandoned part of the delete expression), but I'd like to have more to
>>> go on than how I sense things. So is the behavior of the above spelled out
>>> by the standard?
>
>> "Doctor, it hurts when I poke myself in the eye!" much?
>
>> I don't know if it's spelled out in the standard, but I would be
>> HUGELY surprised if any compiler's generated code would continue to
>> call dtors etc after an exception was thrown. That would essentially
>> mean that operator delete[] is (warning: compiled with head-compiler
>> and tried with head-debugger):
>
>> template<typename TYPE>
>> void OperatorArrayDelete(TYPE* pBegin)
>> {
>> TYPE* pEnd = pBegin+ElementCount(pBegin);
>> while (pEnd!= pBegin)
>> try { (*--pEnd)->~Type(); } catch(...) {}
>> // Well, that catch(...) {} smells to high heaven!
>> SomehowFreeHeap(pBegin);
>> }
>
>> 15.1.must take precedence over 5.3.5/6. It must!!! Aaaaaarghhhhh! :-)
>
>> Goran.
>
> Goran has a damn fine point, depends where the exception is caught, and
> what it then does. IMHO if you get an unexpected exception in a
> destructor then something is potentially broken, and badly! Personally I
> often spend more time on constructors and destructors than most other
> member functions to avoid exceptions there. Getting it right is easier
> than debugging, especially in those situations.

OK, but there's nothing wrong in throwing from a constructor. In fact,
that's by far the best method of signaling construction errors. If you
are trying to avoid an exception from a constructor, you are most
likely using two-phase initialization almost all the time. And if you
do that, you are raising the danger of having objects that you can't
use (because e.g. a File object is useless if not "Open"; do you pre-
pend every read with "isOpen", or do you just cross fingers that you
did open it?).

Goran.


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Goran on
On Apr 30, 7:28 pm, Scott Meyers <NeverR...(a)aristeia.com> wrote:
>> I don't know if it's spelled out in the standard, but I would be
>> HUGELY surprised if any compiler's generated code would continue to
>> call dtors etc after an exception was thrown.
>
> Somehow I think that "the language's behavior should not cause huge
> surprises" is not among its most influential design criteria.
> Heck, entire books have been written about the kinds of things people need
> to watch out for :-)

True, that. After years of C++-ing, I seldom wonder why language I
does what it does. But I indeed see a lot of people being amazed about
X or Y. I don't know if that's saying something good or bad about me.

Goran.

P.S. We need this Daniel guy now, he's the resident expert in closing
the discussion by quoting the standard around here.


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]