Thread View: comp.std.c++
3 messages
3 total messages
Started by Steve Clamage
Mon, 20 Nov 1995 16:34
Re: an optimization I claim is illegal
Author: Steve Clamage
Date: Mon, 20 Nov 1995 16:34
Date: Mon, 20 Nov 1995 16:34
116 lines
3471 bytes
3471 bytes
James Kanze (kanze@gabi-soft.fr) wrote:
>Alex Martelli (martelli@cadlab.it) wrote:
>
>: 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.
>
[code removed, including Derived class deriving from Base class]
>
>There's one obvious problem. The address of Base in Derived is not
>guaranteed to be the same as the address of Derived.
Tim Hollebeek also wrote:
[snip again]
> I think it's pretty clear the answer is no:
>
> [class.dtor] #11:
>
> "... Once a destructor is invoked for an object, the object no longer
> exists; ..."
>
> Now, it is legal to use a (T*) as a (void*) even after the T's life
> has ended, however:
>
> [basic.life] #7:
>
> "If, after the lifetime of an object has ended and while the storage
> which the object occupied still exists, a new object is created at the
> storage location which the original object occupied, a pointer that
> pointed to the original object will automatically refer to the new
> object and, once the lifetime of the new object has started, can be
> used to manipulate the new object, if:
>
> [...]
>
> ... the new object is of THE SAME TYPE as the original object ...
>
> [...]
>
What is meant by the SAME TYPE in the piece of the Draft quoted ? Would
the following code be legal:
-- start here --
#include <iostream.h>
#include <defalloc.h>
struct Base
{
int i;
Base (int val) : i(val) {};
Base () : i(i) {};
virtual ~Base () {};
virtual void f () { cout << "Base" << endl; };
};
struct D2;
struct D1 : public Base
{
D1 (int val) : Base(val) {};
D1 () : Base () {};
virtual ~D1 () {};
virtual void f ();
};
struct D2 : public Base
{
D2 (int val) : Base(val) {};
D2 () : Base () {};
virtual ~D2 () {};
virtual void f ();
};
void D1::f () { cout << "D1" << endl; new (this) D2 (); }
void D2::f () { cout << "D2" << endl; new (this) D1 (); }
int main (void)
{
D1 d1 (7);
Base *pb = &d1;
for (int i = 0; i < 5; i++)
pb->f();
return 0;
}
-- end here --
The output on g++ is 'D1 D2 D1 D2 D1'. The type as seen by the loop
in main does not change, the layout of the types D1 and D2 are the
same, they have the same parents and the same function. Why would it
be illegal in this case ? I do not ask this for purely theoretical
reason: I do use this (in a somewhat more involved ways) in a design
of networked pointers.
[ 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. ]
Re: an optimization I claim is illegal
Author: Dick Menninger
Date: Wed, 22 Nov 1995 02:46
Date: Wed, 22 Nov 1995 02:46
83 lines
3300 bytes
3300 bytes
> ==========Somebody said, 11/20/95==========
> What is meant by the SAME TYPE in the piece of the Draft
quoted ? Would
> the following code be legal:
>
> -- start here --
#include <iostream.h>
#include <defalloc.h>
struct Base
{
int i;
Base (int val) : i(val) {};
Base () : i(i) {};
virtual ~Base () {};
virtual void f () { cout << "Base" << endl; };
};
struct D2;
struct D1 : public Base
{
D1 (int val) : Base(val) {};
D1 () : Base () {};
virtual ~D1 () {};
virtual void f ();
};
struct D2 : public Base
{
D2 (int val) : Base(val) {};
D2 () : Base () {};
virtual ~D2 () {};
virtual void f ();
};
void D1::f () { cout << "D1" << endl; new (this) D2 (); }
void D2::f () { cout << "D2" << endl; new (this) D1 (); }
int main (void)
{
D1 d1 (7);
Base *pb = &d1;
for (int i = 0; i < 5; i++)
pb->f();
return 0;
}
> -- end here --
>
> The output on g++ is 'D1 D2 D1 D2 D1'. The type as seen by the loop
> in main does not change, the layout of the types D1 and D2 are the
> same, they have the same parents and the same function. Why would it
> be illegal in this case ? I do not ask this for purely theoretical
> reason: I do use this (in a somewhat more involved ways) in a design
> of networked pointers.
Wow. This code raises several questions. As coded,
the "object" goes through several ctors as it changes
"personality" without ever a dtor called. Is that legal?
Is that reasonable? That seems to make this a different
problem as you overwrite a living instance through which
the function being executed was called instead of
first destroying it and then creating a new one over
the ashes of the old (or am I confusing two threads).
Is there any requirement that the actual underlying
images be the same size? Can't the compiler could have
other info hidden in the image that could even affect
the offset of this in the memory block used and still
be a conforming compiler? Couldn't that info even be
stuff that could go insane if you did this (list linkage
for various debugging support)?
Good Day
Dick
Dick.Menninger@DaytonOH.ATTGIS.COM
---
[ 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. ]
Re: an optimization I claim is illegal
Author: Fergus Henderson
Date: Wed, 22 Nov 1995 04:48
Date: Wed, 22 Nov 1995 04:48
81 lines
3449 bytes
3449 bytes
Dick Menninger <Dick.Menninger@daytonoh.attgis.com> writes:
>> ==========Somebody said, 11/20/95==========
>
>> What is meant by the SAME TYPE in the piece of the Draft quoted ?
>> Would the following code be legal:
No, the code has undefined behaviour.
The types `D1' and `D2' are not the same.
(The code also has undefined behaviour for other reasons - see below.)
> struct Base
> {
> ...
> virtual void f () { cout << "Base" << endl; };
> };
>
> struct D1 : public Base ...
> struct D2 : public Base ...
>
> void D1::f () { cout << "D1" << endl; new (this) D2 (); }
> void D2::f () { cout << "D2" << endl; new (this) D1 (); }
>
> int main (void)
> {
> D1 d1 (7);
> Base *pb = &d1;
> for (int i = 0; i < 5; i++)
> pb->f();
> return 0;
> }
>>
>> The output on g++ is 'D1 D2 D1 D2 D1'. The type as seen by the loop
>> in main does not change, the layout of the types D1 and D2 are the
>> same, they have the same parents and the same function. Why would it
>> be illegal in this case ? I do not ask this for purely theoretical
>> reason: I do use this (in a somewhat more involved ways) in a design
>> of networked pointers.
>
>Wow. This code raises several questions. As coded,
>the "object" goes through several ctors as it changes
>"personality" without ever a dtor called. Is that legal?
Yes, you are allowed to construct a new object over the top
of an existing object without first calling the destructor
for that existing object.
>Is that reasonable?
A more difficult question. I certainly wouldn't recommend
that sort of coding style in any but extraordinary circumstances.
>Is there any requirement that the actual underlying
>images be the same size?
No, I'm pretty sure there isn't. So therefore the above code has
undefined behaviour - it attempts to construct an object of type `D2'
using the storage for a `D1', and there is no guarantee that this
storage will be large enough or correctly aligned.
If you changed the line
D1 d1 (7);
to
D1 &d1 = *(D1 *) malloc(sizeof(D1) + sizeof(D2));
new (&d1) D1 (7);
then the storage would be definitely large enough to hold either
a D1 or a D2 and would be correctly aligned to hold any object,
so this problem wouldn't arise. But the code would still be undefined
behaviour by 3.8/7, since D1 and D2 are not the same type.
--
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. ]
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads