[PATCH] Fix C++ strict-aliasing issues with memcpy folding

Gabriel Dos Reis gdr@integrable-solutions.net
Wed Feb 3 16:23:00 GMT 2010


On Wed, Feb 3, 2010 at 10:06 AM, Michael Matz <matz@suse.de> wrote:
> Hi,
>
> On Wed, 3 Feb 2010, Gabriel Dos Reis wrote:
>
>> See 3.8/3.
>
> Right.  That's what I'm saying; you aren't allowed to call delete on
> non-existing objects.

That is a bit different from what you're saying.  As I explained earlier,

      delete p;

does two things: (1) run a destructor, (2) and release storage.
Why this distinction is important is seen below.

> That's all fine and well.
>
>> > Now, if you say (as you did upthread) that object *p ceased to exist with
>> > the placement new, then p doesn't point to an object anymore, hence
>> > 'delete p' is undefined.
>>
>> Yes, but I still do not see what the real problem is.
>> Would you mind clarifying?
>
> I'll try: You were saying that my playing with placement new on parts of
> *p, destroys *p.

It ends the lifetime of the previous object, yes.

> The standard then disallows delete p.

more specifically, the standard disallows running a destructor again,
once the object ceases to exist.

> Further in this
> thread it was argued that placement new is supposed to only change types
> of anonymous storage, not static or autmatic storage.  I'm trying to
> connect those statements to derive something that might surprise people,
> and IMO makes placement new to reuse storage even more dubious.

In doing so, I believe we must also be careful in not confusing 'delete p;' with
any of the two sub-tasks it accomplishes.

> The way I derive this goes like so:
>
> struct X { int count; char mem[8]; } *p;
> p = new X;                           // allocates storage (1)

allocate storage AND construct an X object.

> ...                                  // e.g. init all members of *p
> float *f = new (&p->mem[0]) float;   // now *p is no object anymore

Agreed.  So we can't run X's destructor, but we can still
release memory we acquired.

> *f = 1.0;
>
> Now, answer this question: "how do I release the storage allocated at
> (1)?",

   operator delete(p);

> I can't use 'delete p',

you can't use 'delete p' because that would NOT JUST release storage,
it is going to run a destructor first, before releasing storage.  If you
want to release storage, then that is fine: just release the storage.

> but I also can't use 'f' for deallocation
> as it's pointing into the middle of some allocated storage.  I don't have
> any other pointers I might try to use.

sure, you do.  See above.

> I can't use free (p), because I
> don't know if the new at (1) actually used malloc or something else.

yes, but you can use 'operator delete'.

The only thing you have proven so far is that when you use placement new,
you have to be very careful in what you do in terms of destruction and
storage management.  That is not news, and that is not specific to this
type-based analysis issue.  It has always been like that since
placement new was invented.  The C++ standard library is full of
examples of how to manage objects lifetime when one uses placement
new: separate destructor call from storage management.  And that is
precisely what you asked for when you used placement new in the first
place.

-- Gaby



More information about the Gcc-patches mailing list