From: Francis Glassborow on
Thomas Richter wrote:

>
> ??? How should I know how many resources are available? The lack of any
> strong guarantee more or less means that proper handling of resource
> exhaustion is impossible if you insert more than one element at once.
> IOW, all I can do then is to terminate the program? Now, for *that* I
> don't need exceptions, do I?

You are exaggerating. The STL guarantees exception safety. What it does
not do is to guarantee the strong version under all circumstances.

For example suppose that you try to insert a block of ten elements into
a container and that an exception is thrown during this process. You
will still have a stable container in a destructable state. However the
Standard does not guarantee that it is in the same state that it was
prior to your attempt to insert elements.

That seems very reasonable to me. Maybe inserting the first 7 elements
was successful and it only failed on the eighth, unpicking the process
would be costly, indeed preparing for such a failure would be costly
which is why it is left to the programmer to provide that extra if they
need it. The most obvious way to do that is to create a (temporary) copy
of the original container but that is clearly expensive in both time and
resources.

Do you know of a a way to avoid cost and yet provide a strong guarantee
for multiple insertions? If not what magic do you think WG21 has that
you do not?

>
> Similar to the OP, I find it very irritating that at one hand education
> in C++ stresses proper exception handling and exception safety so much,
> while at the other hand the STL provides you with so little to really
> *write* exception safe code when using it. That is, code with
> *guaranteed* behavior in case of exceptions.

With respect, nonsense. AFAICS the Standard Library gives the strongest
guarantees compatible with acceptable performance.

Basically, doesn't that
> mean that one should stay away from the STL when writing code that can
> *truely* handle exceptions correctly, instead of just "hoping the best",
> i.e. an optimistic approach as you seem to suggest?

No optimism required, just an awareness of the different levels of
exception safety and choosing the one appropriate to your work. As
always more safety will generally require more work.

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

From: nmm1 on
In article <ldSdnd8LPeCX_9jRnZ2dnUVZ8hKdnZ2d(a)bt.com>,
Francis Glassborow <francis.glassborow(a)btinternet.com> wrote:
>Thomas Richter wrote:
>
>> Similar to the OP, I find it very irritating that at one hand education
>> in C++ stresses proper exception handling and exception safety so much,
>> while at the other hand the STL provides you with so little to really
>> *write* exception safe code when using it. That is, code with
>> *guaranteed* behavior in case of exceptions.
>
>With respect, nonsense. AFAICS the Standard Library gives the strongest
>guarantees compatible with acceptable performance.

With respect, that is complete nonsense. Firstly, we could argue
about what constitutes 'acceptable performance', which has changed
over the past 20 years, anyway, due to technological changes. But
let's skip that unproductive debate.

Secondly, it is not true even for the STL, let alone for the whole
of the standard library. There is a lot more that could be said,
both with regard to static checking and with regard to reliable
exception handling. From my experience as an implementor of such
things, FAR more can be specified and done, PORTABLY, than most
people realise.

The problem with this is that specifying implementable and usable
exception handling is not easy, and nor is implementing it. My
normal rule is that it needs at least as much effort as dealing
with the non-exception cases. But that is DESIGN effort, and not
a loss of run-time performance.


Regards,
Nick Maclaren.

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

From: Thomas Richter on
Francis Glassborow wrote:

>> ??? How should I know how many resources are available? The lack of any
>> strong guarantee more or less means that proper handling of resource
>> exhaustion is impossible if you insert more than one element at once.
>> IOW, all I can do then is to terminate the program? Now, for *that* I
>> don't need exceptions, do I?
>
> You are exaggerating. The STL guarantees exception safety. What it does
> not do is to guarantee the strong version under all circumstances.

Certainly I am, and it was certainly provocative (but for a reason); I
understand that the STL doesn't provide such a strong guarantee, but
while I understand some of the reasoning behind, I somehow see that in
conflict with the principles of the language. I'll come to that later on.

> For example suppose that you try to insert a block of ten elements into
> a container and that an exception is thrown during this process. You
> will still have a stable container in a destructable state. However the
> Standard does not guarantee that it is in the same state that it was
> prior to your attempt to insert elements.

Certainly, that is understood. But assume that the copy constructors of
my classes cannot throw (otherwise, of course, I agree that all bets are
off, and my code is to blame, and not the STL). However, even then the
STL does not ensure that the container is in a state where either all
new elements are present, or it remained in the original state. I can
certainly arrange that (insert, swap), but without knowing the
implementation of insert, not in a way that is as efficient as it could.
Clearly, such an implementation would be slower (needless to say), but
still required to write code that provides a "useful" guarantee in case
of exceptions.

Or to make it more concrete: Assume that I can ensure you that my copy
constructor doesn't throw, *how* should I deal with exceptions I get
from insert()? Basically, I cannot handle them since I do not know what
the state of the object is after insertion (except that it is to some
degree valid, syntactically at least, but not semantically). Thus, what
should I do then - really as a practical advice?

Realistically, I can only terminate, or scan the object fully to find
what is inserted and what is not. Or I must build a copy/swap around it.
Neither solution is attractive, though knowing the STL implementation,
finding such "stale elements" might be simpler or even trivial.

> That seems very reasonable to me. Maybe inserting the first 7 elements
> was successful and it only failed on the eighth, unpicking the process
> would be costly, indeed preparing for such a failure would be costly
> which is why it is left to the programmer to provide that extra if they
> need it. The most obvious way to do that is to create a (temporary) copy
> of the original container but that is clearly expensive in both time and
> resources.

Yes, true, but maybe - knowing some internals of the implementation - I
could do that in a better way, for some containers at least? Thus, for
example, I could add all elements one after another into a temporary
object which is then atomically added to the container in a last step?

Look, what I'm saying is that I don't understand the "sloppy" approach
of the STL with respect to exceptions, giving me only very limited means
how to handle them. Another way to address this would be if the STL
would give means at hand to "cleanup" a partially affected object - I
don't mind if the exception case is expensive, i.e. I could also think
of an implementation where inserted objects are marked as temporaries,
to be removed in an exception, etc, etc.

> Do you know of a a way to avoid cost and yet provide a strong guarantee
> for multiple insertions? If not what magic do you think WG21 has that
> you do not?

I'm not talking about "magic". I'm talking about giving me more means
how to address exceptions in case they happen. As a third implementation
strategy, I might also be able to deal with insert() in such a way that
I know that of M elements in case of an exception only the first N, N >=
0, N <= M are inserted, so I could remove them. But the STL doesn't even
say that. Could also be the last N. Or instead of that provide me any
information on how I could restore the object - provide me with a
function that tells whether the first N or the last N objects have been
inserted. Anything like that would be, IMHO, required to continue
program execution in a *known* state. But the STL doesn't leave me with
a *known* program state, so how should I continue if I don't know what
happened?

This is my central point: I do not know, and the STL gives me no means,
to get my program back to a known state. It leaves so much freedom to
the implementation that I either need a *completely* different stategy
(copy, insert, swap), must implement myself knowing *my* strategy, or
abort the program.

>> Similar to the OP, I find it very irritating that at one hand education
>> in C++ stresses proper exception handling and exception safety so much,
>> while at the other hand the STL provides you with so little to really
>> *write* exception safe code when using it. That is, code with
>> *guaranteed* behavior in case of exceptions.
>
> With respect, nonsense. AFAICS the Standard Library gives the strongest
> guarantees compatible with acceptable performance.

Now you're provocative - but that's ok, it's my fault to begin with.

Anyhow, I afraid it isn't quite as nonsensical as you seem. It's ok to
say that I cannot expect to have either all or no elements inserted. But
it should give me better means to restore an object into such a state in
case the exception happened. For example, by providing information which
elements have been inserted and which not, or by requiring documentation
on that by the implementation or... I don't see this as a black&white
issue by enforcing the strong guarantee, which I probably don't need.
But what I do need is a known program state to recover from, and an STL
that helps me by doing that.

>> Basically, doesn't that
>> mean that one should stay away from the STL when writing code that can
>> *truely* handle exceptions correctly, instead of just "hoping the best",
>> i.e. an optimistic approach as you seem to suggest?
>
> No optimism required, just an awareness of the different levels of
> exception safety and choosing the one appropriate to your work. As
> always more safety will generally require more work.

Obviously, but not quite the point. When looking at STL guarantees, I do
have the feeling that little thought has been put into how to handle
exceptional cases, but those are the cases that let my programs crash in
worst case, so I - as a program author - should better know how to deal
with them. I see that in conflict with the C++ design where I should
better know what I'm doing, and I should be extremely careful with
exceptions. With as little information as I get, I only have very
limited strategies in handling such cases, whereas my programming praxis
tells me that I usually need more. Terminating a program is the last
resort, and as said, I don't need exceptions for that.

So long,

Thomas

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

From: Francis Glassborow on
Thomas Richter wrote:

>>
>> No optimism required, just an awareness of the different levels of
>> exception safety and choosing the one appropriate to your work. As
>> always more safety will generally require more work.
>
> Obviously, but not quite the point. When looking at STL guarantees, I do
> have the feeling that little thought has been put into how to handle
> exceptional cases, but those are the cases that let my programs crash in
> worst case, so I - as a program author - should better know how to deal
> with them. I see that in conflict with the C++ design where I should
> better know what I'm doing, and I should be extremely careful with
> exceptions. With as little information as I get, I only have very
> limited strategies in handling such cases, whereas my programming praxis
> tells me that I usually need more. Terminating a program is the last
> resort, and as said, I don't need exceptions for that.
>
> So long,

Remember that the STL is just a library without any special support from
the core of the language. So it can only do what any intelligent
programmer can do for themselves. Now despite a very large amount of
thought and discussion among Library experts (WG21 and elsewhere) no-one
has produced (AFAIK) an enhanced STL with stronger guarantees. That does
not prove that it is impossible to do so, but given the desirability for
as much exception safety as possible it does suggest that it requires
methods that are yet to be discovered/invented.

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

From: Louis Lavery on
On 21/07/2010 01:47, Thomas Richter wrote:
> Francis Glassborow wrote:
>
>>> ??? How should I know how many resources are available? The lack of any
>>> strong guarantee more or less means that proper handling of resource
>>> exhaustion is impossible if you insert more than one element at once.
>>> IOW, all I can do then is to terminate the program? Now, for *that* I
>>> don't need exceptions, do I?
>>
>> You are exaggerating. The STL guarantees exception safety. What it
>> does not do is to guarantee the strong version under all circumstances.
>
> Certainly I am, and it was certainly provocative (but for a reason); I
> understand that the STL doesn't provide such a strong guarantee, but
> while I understand some of the reasoning behind, I somehow see that in
> conflict with the principles of the language. I'll come to that later on.
>
>> For example suppose that you try to insert a block of ten elements
>> into a container and that an exception is thrown during this process.
>> You will still have a stable container in a destructable state.
>> However the Standard does not guarantee that it is in the same state
>> that it was prior to your attempt to insert elements.
>
> Certainly, that is understood. But assume that the copy constructors of
> my classes cannot throw (otherwise, of course, I agree that all bets are
> off, and my code is to blame, and not the STL). However, even then the
> STL does not ensure that the container is in a state where either all
> new elements are present, or it remained in the original state. I can
> certainly arrange that (insert, swap), but without knowing the
> implementation of insert, not in a way that is as efficient as it could.

I think there are quite efficient ways to do multiple inserts such that
the container is in a known state should it throw (E.g. a combination of
splice and range constructors for lists and capacity and reserve for
vectors). Maybe not as efficiently as the lib's multiple insert, but
then that's optimised and so doesn't cater for recovery after a throw.
Exception safety does cost, you know.

It does, of course, require some thought.

Louis.

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