C++ Logo

sg12

Advanced search

Re: [ub] Type punning to avoid copying

From: Gabriel Dos Reis <gdr_at_[hidden]>
Date: Thu, 25 Jul 2013 10:45:09 -0500
Howard Hinnant <howard.hinnant_at_[hidden]> writes:

| It was this SO question that started this thread:
|
| http://stackoverflow.com/q/17789928/576911

OK, this version obviously breaks the rule and invoked undefined behavior.
We won't go over that again. But, let me point out that this particular
type-based alias analysis in GCC has a long history and tradition -- and
most certainly longer in high-performance compilers. When it was
implemented in GCC by Mark Mitchell (I think), we found that type-based
alias analysis found lot of broken (C++) codes. You can search GCC
mailing list archive for the long discussions, and also the web. So
it was moved under a dedicated -fstrict-aliasing flag, then after
a while activated at -O2. This is ancient history, by which I mean it
happened *15* years ago at least, circa 1998. Independently, people wanted a
dedicated flag for activating the warning; that was introduced more than
a decade ago, in 2002.

| I'm curious: The accepted answer uses memcpy and the claim is that
| this is a correct answer to the question. That is it does not exhibit
| undefined behavior. My current understanding is that I agree with
| this answer. But I wanted to check here. Do people here agree that:
|
| http://stackoverflow.com/a/17790026/576911
|
| does not break the aliasing rules, or otherwise invoke undefined behavior?

This version does not break aliasing rules. The question of whether it
invokes undefined behavior is less obvious. The current rules guarantee
that if you memcpy() to a place, and memcpy() the same bytes back, you
get the original value and that is well defined. The rules also say
that if you don't initialize an object, but you do a read access you
invoke undefined behavior unless the object is of character type or array
thereof. Now, there is an interesting twist here, which is that int32_t
admits no trap representation (just like characters), I cannot find a
rule a rule that says that even if int32_t object isn't initialized it
is OK, or whether memcpy() into the object is initialization. Note, the
first memcpy() isn't from an int32_t.

If that analysis is correct, I would welcome a rule in the language that
says that memcpy() into an object of type that admits no trap
representation is equivalent to initialization with value obtained from
appropriate interpretation of the value representation bits of the
"initializing byte" sequence. I think this won't hinder existing
program transformation since memcpy() is essentially understood as
ending previous object lifetime and starting a new one.

-- Gaby

Received on 2013-07-25 17:45:27