Undefined behavior - 2 queries

H

Harald van =?UTF-8?B?RMSzaw==?=

Peter said:
I don't think it does. If you think float and int variables are somehow
special, use malloced memory instead:

The rules for dynamically allocated memory are different. Dynamically
allocated memory gets its effective type from whatever data is stored in
it, while declared objects get their effective types from the declarations.
void *p1, *p2;
float *fp;
int *ip;

assert(sizeof (int) == sizeof (float));
p1 = malloc(sizeof (float));
p2 = malloc(sizeof (int));
fp = p1;
ip = p2;
*fp = 42.0;

*fp now has an effective type of float.
memcpy(p2, p1, sizeof (float));

For dynamically allocated memory (but only for that!), memcpy copies the
effective type of *fp to *ip...
/* do something with *ip */

....and if you actually do something with *ip here, you're using an lvalue of
type int to read something which has float as its effective type, meaning
the behaviour is not defined by the C standard.

If you had not used malloc, the effective type of int would have been
preserved, because a declared object cannot have its effective type
altered.
memcpy(p1, p2, sizeof (float));


How is this different from

p1 = malloc(sizeof (float));
fp = p1;
ip = p1;
*fp = 42.0;
/* do something with *ip */

?

For dynamically allocated memory, there is no difference.
You are accessing memory with the same content the same way. If the
sizeof (float) bytes pointed to by p1 are a float which cannot be
accessed as an integer after the assignment (*fp = 42.0), so are the
sizeof (float) bytes pointed to by p2 after the first memcpy.

Correct, but this isn't about "a float which cannot be accessed as an
integer". It is already stated as an implementation detail that a float
_can_ be accessed as an integer. This is about how to access it without
violating C's aliasing rules.
 
P

Peter J. Holzer

The rules for dynamically allocated memory are different.

Where do you read that distinction?

Correct, but this isn't about "a float which cannot be accessed as an
integer". It is already stated as an implementation detail that a float
_can_ be accessed as an integer.

"cannot be accessed without causing undefined behaviour". I assumed that
the context was clear.

hp
 
T

Thad Smith

christian.bau said:
There is no way in conforming Standard C to access the representation
of a float through type int, unsigned int, long or long int, even
though this would be very useful.
Agreed.

There is not even a method that
works in practice on a reasonable range of existing compilers that are
in common use. On some compilers access through a pointer of the
integer type will "work", on others using a union "works". It is
tricky, it depends on the level of compiler optimisation, it depends
on the exact circumstances, and it is just hard to get right.

I disagree here. In my experience, most processors utilize all bits of
an unsigned int as value bits, allowing a union of float and a
suitable-selected unsigned int to access all the bits within a float.
Of course the significance of the bits is dependent on the particular
system.

Your experience may be different. On what systems does compiler
optimization affect the access of float representation through a union
with unsigned int?
 
H

Harald van =?UTF-8?B?RMSzaw==?=

Peter said:
Where do you read that distinction?

C99 6.5p6:
"The effective type of an object for an access to its stored value is the
declared type of the object, if any. 72) [...]
72) Allocated objects have no declared type."

The effective type is further explained in the rest of that and the
following paragraph.
"cannot be accessed without causing undefined behaviour". I assumed that
the context was clear.

It wasn't to me, but it is now. Thanks for the clarification.
 
B

Bart van Ingen Schenau

Peter said:
I don't think it does. If you think float and int variables are
somehow special, use malloced memory instead:

void *p1, *p2;
float *fp;
int *ip;

assert(sizeof (int) == sizeof (float));
p1 = malloc(sizeof (float));
p2 = malloc(sizeof (int));
fp = p1;
ip = p2;
*fp = 42.0;
memcpy(p2, p1, sizeof (float));
/* do something with *ip */
memcpy(p1, p2, sizeof (float));

Here, the compiler must copy the representation of *fp into *ip (and
later back again).
Any meddling you do to *ip in between should be reflected back in *fp
after the copy back.
How is this different from

p1 = malloc(sizeof (float));
fp = p1;
ip = p1;
*fp = 42.0;
/* do something with *ip */

Due to the aliasing rules, the compiler may assume (and some DO assume)
that any changes made to *ip will not affect *fp, because they are
pointers to unrelated types and therefor can't be aliases.

The fact that ip and fp point to the same block of memory simply means
that you invoked UB by breaking the aliasing rules.
Bart v Ingen Schenau
 
C

Chris Torek

... In my experience, most processors utilize all bits of
an unsigned int as value bits, allowing a union of float and a
suitable-selected unsigned int to access all the bits within a float.
Of course the significance of the bits is dependent on the particular
system.

Your experience may be different. On what systems does compiler
optimization affect the access of float representation through a union
with unsigned int?

GCC on x86, for one. The particular case here was a union of
"double" with an array of two 32-bit integers, rather than "float"
with a single 32-bit integer, but the problem was that the compiler's
alias analysis made the assumption that fiddling with the integer
portion of the union left the double portion unchanged, so that an
attempt to build an infinity and/or adjust an exponent (I have
forgotten some of the details) failed.

We got around the problem with a rather heavy-handed application
of "volatile" (not my preferred solution, but it worked, and I was
overruled on "really fixing" the code). In addition to that, some
GCC-internals people claimed that this was a bug in GCC and would
be fixed at some point.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top