C++ Logo

sg12

Advanced search

Re: [ub] type punning through congruent base class?

From: Richard Smith <richardsmith_at_[hidden]>
Date: Fri, 17 Jan 2014 15:42:52 -0800
On 17 January 2014 15:19, Gabriel Dos Reis <gdr_at_[hidden]> wrote:

> | From what I've learned in this thread, the (rough) intended C++ model for
> | PODs (assuming memory of the right size/alignment) would seem to be "the
> | lifetime of a B starts when you write to the memory as a B, and ends
> when you
> | free the memory or write to the memory as different type." [Disclaimer:
> I'm
> | not sure if "read from the memory as a B" also starts lifetime."]
>
> that would be close to what C does with effective types.
>
> | I think we can do better,
>
> Same here.
>
> | but it seems like that's the (rough) intent of the
> | status quo, leaving aside the question of whether the wording actually
> says
> | that.
> |
> |
> | *If* that is the (rough) intent, then in:
> |
> |
> | void *p = malloc(sizeof(B)); // 1
> |
> | B* pb = (B*)p; // 2
> |
> | pb->i = 0; // 3
> |
> | short* ps = (short*)p; // 4
> | *ps = 0; // 5
> |
> | free(p); // 6
> |
> |
> |
> |
> | I assume that the reasoning would be that:
> |
> | * line 3 starts the lifetime of a B (we're writing to the bits of a
> B member,
> | not just any int)
>
> line 3 does not write as a B, so it wouldn't count -- just like in C.
>

Would that not give 'pb->i = 0' undefined behavior, because 'pb' does not,
in fact, point to a B object?


The only clear governing rule I can find is 3.8/5, but that only applies if
the storage ever actually contains a B object. Consider:

  void *p = malloc(sizeof(B));
  B *pb = (B*)p;
  pb->i = 0;
  // ...
  new (p) B;

In this example, "pb->i = 0" has undefined behavior, because we performed
member access on a pointer that points to storage where a B object will
later be constructed. It seems strange that the definedness of 'pb->i = 0'
would depend on how the storage is used later.

| * line 5 ends the lifetime of that B and begins the lifetime of a
> short
> | * line 6 ends the lifetime of that short
>
> Agreed.
>
> | Again ignoring whether this is desirable, is that (roughly) the intent
> of the
> | current wording?
>
> Almost: we never started the lifetime of a B object.
>
> | If yes, does the wording express it (a) accurately and (b) clearly?
>
> My understanding is "no" for both.


Hear, hear =)


> | Finally, regardless of the above answer, do we want to change anything
> about
> | the legality or semantics of the above type-punning code, such as
> possibly
> | having a "type-safe mode" where such code is somehow not allowed unless
> in
> | an "extern "C-compat"" block or something?
>
> This is a good question! Which definitely needs a paper :-)
>
> My view is that if the storage isn't declared or accessed as a B, then it
> isn't a B .
>

It seems you don't consider member access as a B to qualify here. Is that
your intent?

Received on 2014-01-18 00:42:54