Подтвердить что ты не робот

Что такое "частично перекрывающиеся объекты"?

Я просто просматривал все возможные Undefined Behaviors в этом потоке, и один из них

Результат присвоения частично перекрывающимся объектам

Я задавался вопросом, может ли кто-нибудь дать мне определение того, что такое "частично перекрывающиеся объекты", и пример в коде того, как это можно было бы создать?

4b9b3361

Ответ 1

Как указано в других ответах, союз является наиболее очевидным способом его организации.

Это еще более ясный пример того, как частично перекрывающиеся объекты могут возникнуть со встроенным оператором присваивания. В этом примере не будет отображаться UB, если бы не частичные перекрывающиеся ограничения объектов.

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
}

Вы можете получить возможное частичное перекрытие даже с объектами того же типа. Рассмотрим этот пример в случае, когда short строго больше char для реализации, которая не добавляет отступ к 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.
}

Ответ 2

A union является хорошим примером для этого.
Вы можете создать структуру памяти с перекрывающимися членами.

например (из MSDN):

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

теперь, если вы используете назначение char, все остальные члены undefined. Это потому, что они находятся в одном блоке памяти, и вы только установили фактическое значение для его части:

DATATYPE blah;
blah.ch = 4;

Если вы затем попытаетесь получить доступ к blah.i или blah.d или blah.f, они будут иметь значение undefined, (потому что только первый байт, который является char, имеет значение)

Ответ 3

Это относится к проблеме сглаживания указателей, которая запрещена на С++, чтобы компиляторы упрощали оптимизацию времени. Хорошее объяснение проблемы можно найти в этой теме

Ответ 4

Может быть, он подразумевает строгое правило псевдонимов? Объект в памяти не должен пересекаться с объектом другого типа.

"Строгое сглаживание - это предположение, сделанное компилятором C (или С++), что указатели на разузнавание объектов разных типов никогда не будут ссылаться на одно и то же место памяти (то есть псевдонимы друг друга.)"

Ответ 5

В каноническом примере используется 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 */

Причина, по которой memcpy - это поведение undefined, заключается в том, что для выполнения копии нет требуемого алгоритма. В этом случае в качестве безопасной альтернативы был введен memmove.