🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.std.c++
Article #3357

Re: Correctness of compilers behavior

#3357
From: Steve Clamage
Date: Tue, 20 Feb 1996 21:42
85 lines
4001 bytes
In article UAA01735@kronstadt.rahul.net, Ian T Zimmerman <itz@rahul.net> writes:
>In article <4g3i93$9lp@mulga.cs.mu.OZ.AU> fjh@munta.cs.mu.OZ.AU
>(Fergus Henderson) writes:
>
>> >  for (unsigned i=0; i<size; ++i) {
>> >    (bptr+i)->~B();
>> >    new(aptr+i) A;
>> >  }
>> >
>
>> >int main(void)
>> >{
>> >  A* arr=foo(2);
>> >  delete [] arr;
>> 
>> This has undefined behaviour.  It contravenes 5.3.5[expr.delete]/2, which
>> says that the expression passed to `delete []' must be a pointer to the
>> first element of an array of objects allocated with `new []'; this is not
>> the case, because although there once was such an array at that memory
>> location, its lifetime ended when the memory was overwritten by the calls
>> to placement new (see 3.8[basic.life]/1).
>
>Is it relevant here that A and B are unrelated classes? 

No. It only matters that A and B are not the same type. If A were derived
from B or vice-versa the code would still be wrong. Example:
	class A : public B { ... };
	B* p = new A[10]; // legal, but a bad idea
	delete[] p; // error that does not have to be diagnosed 

Such code is valid for single objects, but not for arrays. Although an A
is-a B, an array of A is NOT an array of B. Ordinarily you don't want
C-style arrays of objects, especially polymorphic objects. You probably
want an array of pointers so that you get object instead of value semantics,
or an array class of values to avoid the inconvenient properties of C-style
arrays.

>What about the following code?
>
>A a;
>
>A* as = new A [10];
>
>for (int i = 0; i < 10; ++i) {
>    new (&as[i]) A(a);
>}
>delete [] as;

It is valid to construct an object on top of the storage previously
used for another object of the same type, so this code is mostly OK.
Notice that you don't destroy the objects that were constructed with
the default constructor.

In the general case you would want to destroy the original objects
before building new objects in their storage locations. Related to
this point, the compiler will construct the original objects from
index 0 up to index 9, and will destroy them in the reverse order.
If the objects have any inter-dependencies, you might need to
mimic that behavior to ensure a valid program. So you might write:

	A* as = new A[10]; // construct as[0] through as[9] in that order
	for( int i=10; --i>=0; )
		as[i]->~A(); // destroy in reverse order
	for( int i=0; i<10; ++i )
		new (&as[i]) A(a); // contruct from as[0] through as[9]
	...
	delete[] as; // destroys as[9] down to as[0]

If all you want is an array of values, you don't have to go through the
extra construction and destruction if the number of elements is known
at compile time:
	A as[10] = { a, a, a, a, a, a, a, a, a, a };
or perhaps
	A as[10] = { A(arg0), A(arg1), A(arg2), ... , A(arg9) };
to get different values in different slots.

---
Steve Clamage, stephen.clamage@eng.sun.com
---
[ To submit articles: Try just posting with your newsreader.  If that fails,
                      use mailto:std-c++@ncar.ucar.edu
  FAQ:    http://reality.sgi.com/employees/austern_mti/std-c++/faq.html
  Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu 
]
Technical Details
Message-ID: <4gdc37$cqv@engnews1.Eng.Sun.COM>
Path: arc1-ca.pugleaf.net!chronicle.mti.sgi.com!austern
References: <199602180416.UAA01735@kronstadt.rahul.net>

Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!chronicle.mti.sgi.com!austern
From: clamage@Eng.Sun.COM (Steve Clamage)
Newsgroups: comp.std.c++
Subject: Re: Correctness of compilers behavior
Date: 20 Feb 1996 13:42:34 PST
Organization: Sun Microsystems Inc.
Approved: austern@isolde.mti.sgi.com
Message-ID: <4gdc37$cqv@engnews1.Eng.Sun.COM>
References: <199602180416.UAA01735@kronstadt.rahul.net>
Reply-To: clamage@Eng.Sun.COM
NNTP-Posting-Host: isolde.mti.sgi.com
X-Original-Date: 20 Feb 1996 20:48:39 GMT
X-Auth: PGPMoose V1.1 PGP comp.std.c++
 iQBVAwUBMSpAYky4NqrwXLNJAQEWQAH/RkJZoKQGhF+SNUkGeSgA5GsjcvE7eemd
 DndF/IF8DUsEzYY/bOY4hnCNw7kf4JAoLDpk5bPMujB4razPHQPP4w==
 =Rh5f
Originator: austern@isolde.mti.sgi.com