13

I was just going through all the possible Undefined Behaviours in this thread, and one of them is

The result of assigning to partially overlapping objects

I wondered if anyone could give me a definition of what "partially overlapping objects" are and an example in code of how that could possibly be created?

Community
  • 1
  • 1
Tony The Lion
  • 61,704
  • 67
  • 242
  • 415

5 Answers5

5

As pointed out in other answers, a union is the most obvious way to arrange this.

This is an even clearer example of how partially overlapping objects might arise with the built in assignment operator. This example would not otherwise exhibit UB if it were not for the partially overlapping object restrictions.

union Y {
    int n;
    short s;
};

void test() {
    Y y;
    y.s = 3;     // s is the active member of the union
    y.n = y.s;   // Although it is valid to read .s and then write to .x
                 // changing the active member of the union, .n and .s are
                 // not of the same type and partially overlap
}

You can get potential partial overlap even with objects of the same type. Consider this example in the case where short is strictly larger than char on an implementation that adds no padding to X.

struct X {
    char c;
    short n;
};

union Y {
    X x;
    short s;
};

void test() {
    Y y;
    y.s = 3;     // s is the active member of the union
    y.x.n = y.s; // Although it is valid to read .s and then write to .x
                 // changing the active member of the union, it may be
                 // that .s and .x.n partially overlap, hence UB.
}
CB Bailey
  • 755,051
  • 104
  • 632
  • 656
3

A union is a good example for that.
You can create a structure of memory with overlapping members.

for example (from MSDN):

union DATATYPE    // Declare union type
{
    char   ch;
    int    i;
    long   l;
    float  f;
    double d;
} var1;

now if you use assign the char member all other member are undefined. That's because they are at the same memory block, and you've only set an actual value to a part of it:

DATATYPE blah;
blah.ch = 4;

If you will then try to access blah.i or blah.d or blah.f they will have an undefined value. (because only first byte, which is a char, had its value set)

Foo Bah
  • 25,660
  • 5
  • 55
  • 79
Yochai Timmer
  • 48,127
  • 24
  • 147
  • 185
  • 2
    Good example, but to show the UB in question your example should probably be: `blah.ch = 4; blah.i = blah.ch;` to avoid confusion with the other UB available with unions. – CB Bailey Sep 03 '11 at 11:50
  • But why in some articles about strict aliasing rule, authors say that only way of converting types byte-to-byte is using unions? – osgx Sep 03 '11 at 11:50
  • @osgx You could do that if you know that they are in the exact same size and are byte-to-byte convertible. in this example they are not of the same size and are not byte-to-byte convertible – Yochai Timmer Sep 03 '11 at 11:54
  • 1
    @osgx the behavior is undefined if you are assigning via a member and trying to access another member of a larger size. If you assign the double and try to access the char value, the result is well-defined. – Foo Bah Sep 04 '11 at 04:25
1

This refers to the problem of pointer aliasing, which is forbidden in C++ to give compilers an easier time optimizing. A good explanation of the problem can be found in this thread

Community
  • 1
  • 1
ComicSansMS
  • 51,484
  • 14
  • 155
  • 166
0

May be he mean a strict aliasing rule? Object in memory should not overlap with object of other type.

"Strict aliasing is an assumption, made by the C (or C++) compiler, that dereferencing pointers to objects of different types will never refer to the same memory location (i.e. alias each other.)"

osgx
  • 90,338
  • 53
  • 357
  • 513
0

The canonical example is using memcpy:

char *s = malloc(100);
int i;
for(i=0; i != 100;++i) s[i] = i; /* just populate it with some data */
char *t = s + 10;  /* s and t may overlap since s[10+i] = t[i] */
memcpy(t, s, 20); /* if you are copying at least 10 bytes, there is overlap and the behavior is undefined */

The reason why memcpy is undefined behavior is because there's no required algorithm for performing the copy. In this circumstance, memmove was introduced as a safe alternative.

Foo Bah
  • 25,660
  • 5
  • 55
  • 79