Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is pointer arithmetic on inactive member of a union UB?

Let's consider this example code:

struct sso
{
    union {
        struct {
            char* ptr;
            char size_r[8];
        } large_str;
        char short_str[16];
    };

    const char* get_tag_ptr() const {
        return short_str+15;
    }
};

In [basic.expr] it is specified that pointer arithmetic is allowed as long as the result points to another element of the array (or past the end of an object or of the last element). Nevertheless it is not specified in this setion what happens if the array is an inactive member of a union. I believe it is not an issue short_str+15 is never UB. Is it right?

The following question clearly showes my intent

like image 633
Oliv Avatar asked Jan 10 '18 13:01

Oliv


1 Answers

Writing return short_str+15;, you take the address of an object whose lifetime may have not started, but this does not result in undefined behavior unless you dereference it.

[basic.life]/1.2

if the object is a union member or subobject thereof, its lifetime only begins if that union member is the initialized member in the union, or as described in [class.union].

and

[class.union]/1

In a union, a non-static data member is active if its name refers to an object whose lifetime has begun and has not ended ([basic.life]). At most one of the non-static data members of an object of union type can be active at any time, that is, the value of at most one of the non-static data members can be stored in a union at any time.

but

[basic.life]/6

Before the lifetime of an object has started but after the storage which the object will occupy has been allocated or, after the lifetime of an object has ended and before the storage which the object occupied is reused or released, any pointer that represents the address of the storage location where the object will be or was located may be used but only in limited ways. For an object under construction or destruction, see [class.cdtor]. Otherwise, such a pointer refers to allocated storage ([basic.stc.dynamic.allocation]), and using the pointer as if the pointer were of type void* , is well-defined. Indirection through such a pointer is permitted but the resulting lvalue may only be used in limited ways, as described below.
- [list unrelated to unions]

like image 79
YSC Avatar answered Sep 20 '22 12:09

YSC