다음 구조를 고려하십시오.
struct s {
int a, b;
};
일반적으로 1 이면이 구조체의 크기는 8이고 정렬은 4입니다.
두 개의 struct s
객체를 생성하고 (보다 정확하게는 두 개의 객체를 할당 된 저장소에 쓰면) 두 번째 객체가 첫 번째 객체와 겹치는 경우 어떻게해야합니까?
char *storage = malloc(3 * sizeof(struct s));
struct s *o1 = (struct s *)storage; // offset 0
struct s *o2 = (struct s *)(storage + alignof(struct s)); // offset 4
// now, o2 points half way into o1
*o1 = (struct s){1, 2};
*o2 = (struct s){3, 4};
printf("o2.a=%d\n", o2->a);
printf("o2.b=%d\n", o2->b);
printf("o1.a=%d\n", o1->a);
printf("o1.b=%d\n", o1->b);
이 프로그램에 대해 정의되지 않은 동작이 있습니까? 그렇다면 어디에 정의되지 않습니까? UB가 아닌 경우 항상 다음을 인쇄해야합니다.
o2.a=3
o2.b=4
o1.a=1
o1.b=3
특히, 겹치는 객체 가 쓰여질 o1
때 가리키는 객체에 어떤 일이 발생하는지 알고 싶습니다 o2
. 여전히 클로저되지 않은 부분 ( o1->a
) 에 액세스 할 수 있습니까? clobbered 부분에 액세스하는 것은 o1->b
단순히 액세스하는 것과 동일 o2->a
합니까?
어떻게 효과적인 유형은 여기에 적용? 겹치지 않는 객체와 마지막 저장소와 동일한 위치를 가리키는 포인터에 대해 이야기 할 때는 규칙이 명확하지만, 객체의 유효 유형 또는 겹치는 객체에 대해 이야기 할 때는 덜 명확합니다.
두 번째 쓰기가 다른 유형 인 경우 어떤 것이 변경됩니까? 회원이 있다면 말 int
과 short
아닌 두 가지 int
의?
여기에서 놀고 싶다면 godbolt 가 있습니다.
1 이 답변은 그렇지 않은 플랫폼에 적용됩니다. 예를 들어 일부는 크기가 4이고 정렬이 2 일 수 있습니다. 크기와 정렬이 동일한 플랫폼에서는 정렬 된 겹치는 객체 때문에이 질문이 적용되지 않습니다. 불가능하지만 그런 플랫폼이 있는지 확실하지 않습니다.