Article View: comp.std.c++
Article #2684Re: an optimization I claim is illegal
From: Fergus Henderson
Date: Tue, 21 Nov 1995 16:04
Date: Tue, 21 Nov 1995 16:04
112 lines
4636 bytes
4636 bytes
martelli@cadlab.it (Alex Martelli) writes:
>In a debate over on comp.compilers, there was some discussion of
>whether it would be legal for a compiler to optimize the following
>snippet of code...:
>
>class P {
>public: virtual void f();
> // etc
>};
>
>// with a P* p
> for(i=0;i<1000;i++)
> p->f();
>
>by hoisting out of the loop the virtual lookup for f()'s address.
Yes, I saw that debate. I believe that the optimization is legal
according to the current draft standard. See section 3.8 [basic.life],
"Object Lifetime". The committee was quite deliberate in its intent to
make sure that this optimizations and other similar optimizations were
legal.
>#include <iostream>
>
>class Base {
>public: virtual void f() {cout<<"Base ";}
>};
>class Derived: public Base {
> int countdown;
>public: Derived(int n=2):countdown(n) {}
> virtual void f();
>};
>int main()
>{
> Base *p=new Derived;
> for(int i=0;i<4;i++)
> p->f();
> cout<<endl;
> return 0;
>}
>
>and, separately compiled perhaps,
>
>#include <iostream>
>#include <new>
>// above-seen declarations of Base and Derived, then:
> virtual void Derived::f() {
> cout<<"Derived ";
> if(--n==0) {
> this->~Derived();
> new(this) Base;
> }
> }
>
>Isn't this a strictly conformant, well-defined program,
No. According to 3.8, it has undefined behaviour. It violates 3.8/6.
The pointer `p' is dereferenced after the lifetime of the object
it points to has ended (since the storage has been reused).
| 3.8 Object Lifetime [basic.life]
| 5 A program may end the lifetime of any object by reusing the storage
| which the object occupies or by explicitly calling the destructor for
| an object of a class type with a non-trivial destructor.
[...]
| 6 After the lifetime of an object has ended and while the storage which
| the object occupied still exists, any pointer to the original object
| can be used but only in limited ways. Such a pointer still points to
| valid storage and using the pointer as a pointer to the storage where
| the object was located, as if the pointer were of type void*, is well-
| defined. However, using the pointer to refer to the original object
| is no longer valid. In particular, such a pointer cannot be derefer-
| enced; for a non-POD class type T, a pointer of type T* that points to
| the original object cannot be the operand of a static_cast
| (_expr.static.cast_) (except when the conversion is to void* or char*)
| and cannot be the operand of a dynamic_cast (_expr.dynamic.cast_); if
| T is a class with a non-trivial destructor, such a pointer cannot be
| used as the operand of a delete-expression. [Example:
| struct B {
| virtual void f();
| void mutate();
| virtual ~B();
| };
|
| struct D1 : B { void f(); };
| struct D2 : B { void f(); };
| void B::mutate() {
| new (this) D2; // reuses storage - ends the lifetime of '*th
| is'
| f(); // undefined behavior
| ... = this; // ok, 'this' points to valid memory
| }
|
| void g() {
| void* p = malloc(sizeof(D1) + sizeof(D2));
| B* pb = new (p) D1;
| pb->mutate();
| &pb; // ok: pb points to valid memory
| void* q = pb; // ok: pb points to valid memory
| pb->f(); // undefined behavior, lifetime of *pb has en
| ded
| }
| --end example]
--
Fergus Henderson WWW: http://www.cs.mu.oz.au/~fjh
fjh@cs.mu.oz.au PGP: finger fjh@128.250.37.3
[ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
Contact address: std-c++-request@ncar.ucar.edu. The moderation policy
is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Technical Details
Message-ID:
<9532601.3781@mulga.cs.mu.OZ.AU>Path:
arc1-ca.pugleaf.net!engnews1.Eng.Sun.COM!taumet!clamageReferences:
<martelli.816557310@cadlab>Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!engnews1.Eng.Sun.COM!taumet!clamage From: fjh@munta.cs.mu.OZ.AU (Fergus Henderson) Newsgroups: comp.std.c++ Subject: Re: an optimization I claim is illegal Date: 21 Nov 1995 16:04:40 GMT Organization: Computer Science, University of Melbourne, Australia Sender: news@cs.mu.OZ.AU (CS-Usenet) Approved: clamage@eng.sun.com (comp.std.c++) Message-ID: <9532601.3781@mulga.cs.mu.OZ.AU> References: <martelli.816557310@cadlab> NNTP-Posting-Host: taumet.eng.sun.com Originator: clamage@taumet