From: Andre Kaufmann on
red floyd wrote:
> On Apr 29, 12:51 am, joe <jgr...(a)doubletake.com> wrote:
>> string a = "some big string....";
>> string b = a; // works
>> b[3] = 'c'; // bam out of memory because cow allocated on me
>>
>
> This example, right here, is the best argument I have seen against
> CoW.
> Thanks.

I don't favor COW but I don't see a significant difference between:

string b = a; // Can't allocate -> throw badalloc;

and

b[3] = 'c'; operator[](int) -> Can't alloc -> throw

Andre


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

From: joe on
Andre Kaufmann wrote:

> red floyd wrote:
>> On Apr 29, 12:51 am, joe <jgr...(a)doubletake.com> wrote:
>>> string a = "some big string....";
>>> string b = a; // works
>>> b[3] = 'c'; // bam out of memory because cow allocated on me
>>>
>>
>> This example, right here, is the best argument I have seen against
>> CoW.
>> Thanks.
>
> I don't favor COW but I don't see a significant difference between:
>
> string b = a; // Can't allocate -> throw badalloc;
>
> and
>
> b[3] = 'c'; operator[](int) -> Can't alloc -> throw
>
> Andre
>
>

string b = c;
I expect allocation here.


b[3] = 'c';

what would make you think this would allocate? Arrays dont, vectors
don't, pointers don't, maps don't if the element exists (they do if the
element doesn't, but that has always been a mistake imo).

joe

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

From: Andre Kaufmann on
Mathias Gaunard wrote:
> [...]
> All code should be basic exception-safe, so unpredicted behavior
> shouldn't be possible;

There is IMHO no 100% exception safe application.
Another exception during stack unwinding and your application blows up.
And this conditions aren't always obvious.

It's just the same as writing safe code.
There isn't 100% safe code.

> whatever happens invariants are maintained and
> the program remains in a valid state.
> Note basic exception-safe is guaranteed by the use of RAII.

Which doesn't prevent exceptions during stack unwinding or doesn't prevent any data loss, because the data can't be stored, passed to a database etc.

Or if I think how much trouble I had with half constructed -> half baked objects, which threw an exception in the constructor initializer....

It's IMHO a huge difference between a deterministic error condition, which throws an exception and an insufficient memory condition.
The OS gets unstable and the application too.
I differentiate between allocating huge memory blocks or simply running out of memory because to much small chunks of memory have been allocated.

>
>> Stack unwinding helps to recover from a low memory condition, but data
>> may be lost anyways.
>
> Indeed, no data loss is the strong exception-safety guarantee, which
> can be non-trivial to provide for certain operations, and can cost
> more than the basic guarantee.

Nobody is perfect and there are so much conditions, which can't be predicted 100%. RAII helps for sure.

>
> [...]
> If you can't rely on such primitives to be nothrow, it is almost
> impossible to write exception-safe code with the strong guarantee.

I think the code will be no more or less exception safe if string operator[] throws or the string constructor. So COW should still be (in this case) exception safe.

>
>> If malloc doesn't throw (older implementations)
>
> Malloc never throws.

Hope you didn't assume that I don't know that a C runtime function can't throw a C++ exception ?
It's for me an abbreviation for memory allocation. But we shouldn't discuss pedantically about that,
for record:

I meant generally C++ memory allocations, precisely operator new(..)

Andre

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

From: Bo Persson on
Andre Kaufmann wrote:
> red floyd wrote:
>> On Apr 29, 12:51 am, joe <jgr...(a)doubletake.com> wrote:
>>> string a = "some big string....";
>>> string b = a; // works
>>> b[3] = 'c'; // bam out of memory because cow allocated on me
>>>
>>
>> This example, right here, is the best argument I have seen against
>> CoW.
>> Thanks.
>
> I don't favor COW but I don't see a significant difference between:
>
> string b = a; // Can't allocate -> throw badalloc;
>
> and
>
> b[3] = 'c'; operator[](int) -> Can't alloc -> throw
>


No?

What about

char& c = b[3]; // operator[](int) -> Can't alloc -> throw


I would be pretty concerned about this one!


As others have mentioned, COW is perhaps not evil in itself, but
combined with the std::string interface it just doesn't work.


Bo Persson






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

From: Mathias Gaunard on
On Apr 30, 6:28 pm, Andre Kaufmann <akfmn...(a)t-online.de> wrote:

> There is IMHO no 100% exception safe application.

Sure there is, it's trivial to achieve if you just use RAII.
By just exception-safe, I mean the basic guarantee.


> Another exception during stack unwinding and your application blows up.
> [...]
> Which doesn't prevent exceptions during stack unwinding

Which is why people make destructors nothrow, even if they don't
enforce it.
Not enforcing it means that if it still happens, the program aborts
instantly with an error message. Not a serious issue.


> or doesn't prevent any data loss, because the data can't be stored, passed to a database etc.

As I already said, RAII only gives the basic guarantee. There is no
automatic way to get the strong guarantee, short of making the world
transactional.

>
> Or if I think how much trouble I had with half constructed -> half baked objects, which threw an exception in the constructor
initializer....

Doesn't happen if you don't make your RAII object wrap multiple
resources at once...


> It's IMHO a huge difference between a deterministic error condition, which throws an exception and an insufficient memory
condition.
> The OS gets unstable and the application too.
> I differentiate between allocating huge memory blocks or simply running out of memory because to much small chunks of memory have
been allocated.

I have no idea what you're talking about there. What is a huge
difference?


> Nobody is perfect and there are so much conditions, which can't be predicted 100%. RAII helps for sure.

Sure it can be predicted. Some operations are nothrow, some are atomic
(strong guarantee), some are just basic. You should write your code in
function of these properties to deduce the property of the code you're
writing: either basic, strong or nothrow.

RAII ensures the code provides the basic guarantee, but not more.


> > [...]
> > If you can't rely on such primitives to be nothrow, it is almost
> > impossible to write exception-safe code with the strong guarantee.
>
> I think the code will be no more or less exception safe if string operator[] throws or the string constructor. So COW should still
be (in this case) exception safe.

That's a quite ironic thing to say, as you were just talking about how
problematic things that throw during stack unwinding are.

Writing exception-safe code requires that a set of operations be
nothrow, since they're the operations you're going to perform in case
of error -- or in case of stack unwinding as you were talking about --
to rollback to some previous or just safe state.
If an operation as basic as writing to memory could throw, then there
is no way you could do much.


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