From: Andre Kaufmann on 29 Apr 2010 20:05 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 30 Apr 2010 02:18 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 30 Apr 2010 02:28 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 30 Apr 2010 05:25 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 30 Apr 2010 05:26
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! ] |