Topic: Value of pointer if new expr throws


Author: Scott Meyers <NeverRead@aristeia.com>
Date: Wed, 17 Feb 2010 11:16:43 CST
Raw View
  From a colleague:

> When you have an allocation, initialization, and assignment, as in
>
> Node *n = 0;
> ~~~
> n = new Node(init);
>
> We know that if the allocation of memory for Node succeeds and the
> constructor for Node throws, then the allocated memory will be recovered
> by the corresponding operator delete.
>
> However, I think that the compiler is allowed to do the assignment of
> the address to n BEFORE the constructor is called.  If that's the case,
> then the value of n (formerly null) will be corrupted if the constructor
> throws an exception; n will point to deleted memory.
>
> Therefore I claim that the code should be written as follows:
>
> Node *n = 0;
> ~~~
> Node *tmp = new Node(init);
> n = tmp;
>
> Is this your understanding as well, or am I wrong about this?

I can't find anything in the C++03 standard that guarantees that in

    n = new Node(init);

n won't be modified if the new expression throws.  Am I overlooking something,
or is my colleague correct?

Please note that this question is about the current standard (C++03), not C++0x.

Thanks,

Scott

--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Gert-Jan de Vos <gert-jan.de.vos@onsneteindhoven.nl>
Date: Wed, 17 Feb 2010 16:26:38 CST
Raw View
On Feb 17, 6:16 pm, Scott Meyers <NeverR...@aristeia.com> wrote:
>   From a colleague:
>
>
>
> > When you have an allocation, initialization, and assignment, as in
>
> > Node *n = 0;
> > ~~~
> > n = new Node(init);
>
> > We know that if the allocation of memory for Node succeeds and the
> > constructor for Node throws, then the allocated memory will be recovered
> > by the corresponding operator delete.
>
> > However, I think that the compiler is allowed to do the assignment of
> > the address to n BEFORE the constructor is called.  If that's the case,
> > then the value of n (formerly null) will be corrupted if the constructor
> > throws an exception; n will point to deleted memory.
>
> > Therefore I claim that the code should be written as follows:
>
> > Node *n = 0;
> > ~~~
> > Node *tmp = new Node(init);
> > n = tmp;
>
> > Is this your understanding as well, or am I wrong about this?
>
> I can't find anything in the C++03 standard that guarantees that in
>
>     n = new Node(init);
>
> n won't be modified if the new expression throws.  Am I overlooking
something,
> or is my colleague correct?
>
> Please note that this question is about the current standard (C++03), not
C++0x.
>
> Thanks,
>
> Scott

1.9-17 describes the sequence points at function entry and exit:

"... There is also a sequence point after the copying of a returned
value
and before the execution of any expressions outside the function 11).
Several contexts in C++ cause evaluation of a function call, even
though
no corresponding function call syntax appears in the translation unit.
[Example: evaluation of a new expression invokes one or more
allocation
and constructor functions; see 5.3.4. ..."

This could be interpreted as no sequence point at constructor exit as
a
constructor does not return a value. Footnote 11) clarifies this:

"11) The sequence point at the function return is not explicitly
specified
in ISO C, and can be considered redundant with sequence points at
full-
expressions, but the extra clarity is important in C++. In C++, there
are
more ways in which a called function can terminate its execution, such
as
the throw of an exception."

Now to me it is still unclear whether the return of a constructor
function is
a sequence point.


--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use
mailto:std-c++@netlab.cs.rpi.edu<std-c%2B%2B@netlab.cs.rpi.edu>
]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: =?ISO-8859-1?Q?Daniel_Kr=FCgler?= <daniel.kruegler@googlemail.com>
Date: Wed, 17 Feb 2010 17:55:02 CST
Raw View
On 17 Feb., 18:16, Scott Meyers <NeverR...@aristeia.com> wrote:
>   From a colleague:
> > When you have an allocation, initialization, and assignment, as in
>
> > Node *n = 0;
> > ~~~
> > n = new Node(init);
>
> > We know that if the allocation of memory for Node succeeds and the
> > constructor for Node throws, then the allocated memory will be recovered
> > by the corresponding operator delete.
>
> > However, I think that the compiler is allowed to do the assignment of
> > the address to n BEFORE the constructor is called.  If that's the case,
> > then the value of n (formerly null) will be corrupted if the constructor
> > throws an exception; n will point to deleted memory.
>
> > Therefore I claim that the code should be written as follows:
>
> > Node *n = 0;
> > ~~~
> > Node *tmp = new Node(init);
> > n = tmp;
>
> > Is this your understanding as well, or am I wrong about this?
>
> I can't find anything in the C++03 standard that guarantees that in
>
>     n = new Node(init);
>
> n won't be modified if the new expression throws.  Am I overlooking something,
> or is my colleague correct?
>
> Please note that this question is about the current standard (C++03), not C++0x.

The C++03 standard does not specify that clearly, see the
discussion among

http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#672

HTH & Greetings from Bremen,

Daniel Kr   gler


--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]